1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-04-06 01:16:37 +02:00

Merge branch 'master' into winhttp

This commit is contained in:
OJ 2015-03-20 11:59:28 +10:00
commit b7d6eba46b
16 changed files with 951 additions and 777 deletions

@ -76,7 +76,7 @@ void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *byt
}
np->packet_stream = tmp;
size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);
size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);
*size = htons(h->caplen);
data = (unsigned char *)(np->packet_stream + np->packet_stream_length + 2);
@ -438,7 +438,11 @@ Command customCommands[] =
/*
* Initialize the server extension
*/
#ifdef _WIN32
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
#else
DWORD InitServerExtension(Remote *remote)
#endif
{
int peername_len;
struct sockaddr peername;
@ -497,7 +501,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
/*
* Deinitialize the server extension
*/
#ifdef _WIN32
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
#else
DWORD DeinitServerExtension(Remote *remote)
#endif
{
command_deregister_all(customCommands);
@ -507,3 +515,23 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
return ERROR_SUCCESS;
}
/*!
* @brief Get the name of the extension.
* @param buffer Pointer to the buffer to write the name to.
* @param bufferSize Size of the \c buffer parameter.
* @return Indication of success or failure.
*/
#ifdef _WIN32
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
#else
DWORD GetExtensionName(char* buffer, int bufferSize)
#endif
{
#ifdef _WIN32
strncpy_s(buffer, bufferSize, "networkpug", bufferSize - 1);
#else
strncpy(buffer, "networkpug", bufferSize - 1);
#endif
return ERROR_SUCCESS;
}

@ -1197,7 +1197,11 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet)
* @param remote Pointer to the remote instance.
* @return Indication of success or failure.
*/
#ifdef _WIN32
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
#else
DWORD InitServerExtension(Remote *remote)
#endif
{
#ifdef _WIN32
// This handle has to be set before calls to command_register
@ -1271,7 +1275,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
* @param remote Pointer to the remote instance.
* @return Indication of success or failure.
*/
#ifdef _WIN32
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
#else
DWORD DeinitServerExtension(Remote *remote)
#endif
{
command_register_all( customCommands );
@ -1294,8 +1302,16 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
* @param bufferSize Size of the \c buffer parameter.
* @return Indication of success or failure.
*/
#ifdef _WIN32
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
#else
DWORD GetExtensionName(char* buffer, int bufferSize)
#endif
{
#ifdef _WIN32
strncpy_s(buffer, bufferSize, "sniffer", bufferSize - 1);
#else
strncpy(buffer, "sniffer", bufferSize - 1);
#endif
return ERROR_SUCCESS;
}
}

@ -1,370 +1,132 @@
#include "precomp.h"
#include <sys/stat.h>
#ifndef _WIN32
#include <dirent.h>
#endif
/*
* Gets the contents of a given directory path and returns the list of file
* names to the requestor.
*
* TLVs:
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
*/
DWORD request_fs_ls(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR directory;
DWORD result = ERROR_SUCCESS;
LPSTR expanded = NULL, tempFile = NULL;
size_t tempFileSize = 0;
LPSTR baseDirectory = NULL;
struct meterp_stat buf;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
// Enumerate the directory if one was provided
if (!directory)
result = ERROR_INVALID_PARAMETER;
else
{
#ifdef _WIN32
WIN32_FIND_DATA data;
HANDLE ctx = NULL;
#else
DIR *ctx;
struct dirent *data;
#endif
BOOLEAN freeDirectory = FALSE;
LPSTR tempDirectory = (LPSTR)directory;
#ifdef _WIN32
// If there is not wildcard mask on the directory, create a version of the
// directory with a mask appended
if (!strrchr(directory, '*'))
{
if (!(tempDirectory = (LPSTR)malloc(strlen(directory) + 3)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
sprintf(tempDirectory, "%s\\*", directory);
// Dupe!
if (!(baseDirectory = _strdup(directory)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
}
// Otherwise, if it does have an asterisk, we need to scan back and find
// the base directory. If there is no slash, it means we're listing the
// cwd.
else
{
PCHAR slash = strrchr(directory, '\\');
if (slash)
{
*slash = 0;
if (!(baseDirectory = _strdup(directory)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
*slash = '\\';
}
}
// Expand the path
if (!(expanded = fs_expand_path(tempDirectory)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
// Start the find operation
ctx = FindFirstFile(expanded, &data);
#define DF_NAME data.cFileName
#else
expanded = 0;
ctx = opendir(tempDirectory);
if(ctx == NULL)
{
result = errno;
goto out;
}
data = readdir(ctx);
if (!(baseDirectory = _strdup(directory)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
#define DF_NAME data->d_name
#endif
do
{
size_t fullSize = (baseDirectory ? strlen(baseDirectory) : 0) + strlen(DF_NAME) + 2;
// No context? Sucktastic
if (ctx == INVALID_HANDLE_VALUE)
{
result = GetLastError();
break;
}
// Allocate temporary storage to stat the file
if ((!tempFile) || (tempFileSize < fullSize))
{
if (tempFile)
{
free(tempFile);
}
// No memory means we suck a lot like spoon's mom
if (!(tempFile = (LPSTR)malloc(fullSize)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Update the tempFileSize so that we don't allocate if we don't
// need to like a true efficient ninja
tempFileSize = fullSize;
}
// Build the full path
if (baseDirectory)
{
#ifdef _WIN32
sprintf(tempFile, "%s\\%s", baseDirectory, DF_NAME);
#else
sprintf(tempFile, "%s/%s", baseDirectory, DF_NAME);
#endif
}
else
{
sprintf(tempFile, "%s", DF_NAME);
}
// Add the file name to the response
packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, DF_NAME);
// Add the full path
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, tempFile);
// Stat the file to get more information about it.
if (fs_stat(tempFile, &buf) >= 0)
{
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
}
#ifdef _WIN32
} while (FindNextFile(ctx, &data));
#else
} while (data = readdir(ctx));
#endif
#undef DF_NAME
// Clean up resources
if (freeDirectory)
{
free(tempDirectory);
}
if (ctx)
{
#ifdef _WIN32
FindClose(ctx);
#else
closedir(ctx);
#endif
}
}
if (expanded)
{
free(expanded);
}
out:
if (baseDirectory)
{
free(baseDirectory);
}
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}
/*
* Gets the current working directory
*/
DWORD request_fs_getwd(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD directorySize = 4096, realSize;
LPSTR directory = NULL;
DWORD result = ERROR_SUCCESS;
do
{
again:
// Allocate storage for the directory path
if (!(directory = (LPSTR)malloc(directorySize)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
memset(directory, 0, directorySize);
#ifdef _WIN32
if (!(realSize = GetCurrentDirectory(directorySize, directory)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
else if (realSize > directorySize)
{
free(directory);
directorySize = realSize;
goto again;
}
#else
if (!getcwd(directory, directorySize))
{
if (errno == ERANGE && directorySize > 0)
{
// Then we didn't allocate enough to hold the whole path,
// increase the size and try again.
free(directory);
directorySize = directorySize * 2;
goto again;
} else {
dprintf("getcwd failed with errno %d", errno);
break;
}
}
#endif
packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH,
directory);
} while (0);
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
if (directory)
free(directory);
return ERROR_SUCCESS;
}
/*
* Changes the working directory of the process
*
* TLVs:
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
* directory to.
*/
DWORD request_fs_chdir(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR directory;
DWORD result = ERROR_SUCCESS;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (!directory)
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!SetCurrentDirectory(directory))
#else
else if (chdir(directory))
#endif
result = GetLastError();
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}
/*
* Creates a new directory
*
* TLVs:
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
*/
DWORD request_fs_mkdir(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR directory;
DWORD result = ERROR_SUCCESS;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (!directory)
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!CreateDirectory(directory, NULL))
#else
else if (mkdir(directory, 0777))
#endif
result = GetLastError();
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}
/*
* Removes the supplied directory from disk if it's empty
*
* TLVs:
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
*/
DWORD request_fs_delete_dir(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR directory;
DWORD result = ERROR_SUCCESS;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (!directory)
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!RemoveDirectory(directory))
#else
else if (rmdir(directory))
#endif
result = GetLastError();
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
}
#include "precomp.h"
#include "fs_local.h"
void request_fs_ls_cb(void *arg, char *name, char *short_name, char *path)
{
Packet *response = arg;
struct meterp_stat s;
/*
* Add the file name, full path and stat information
*/
packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, name);
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, path);
if (short_name) {
packet_add_tlv_string(response, TLV_TYPE_FILE_SHORT_NAME, short_name);
}
if (fs_stat(path, &s) >= 0) {
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &s, sizeof(s));
}
}
/*
* Gets the contents of a given directory path and returns the list of file
* names to the requestor.
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
*/
DWORD request_fs_ls(Remote * remote, Packet * packet)
{
Packet *response = packet_create_response(packet);
LPCSTR directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
DWORD result;
if (!directory) {
result = ERROR_INVALID_PARAMETER;
} else {
result = fs_ls(directory, request_fs_ls_cb, response);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}
/*
* Gets the current working directory
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
* directory to.
*/
DWORD request_fs_getwd(Remote * remote, Packet * packet)
{
Packet *response = packet_create_response(packet);
char *directory = NULL;
DWORD result;
result = fs_getwd(&directory);
if (directory != NULL) {
packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH, directory);
free(directory);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}
/*
* Changes the working directory of the process
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
* directory to.
*/
DWORD request_fs_chdir(Remote * remote, Packet * packet)
{
Packet *response = packet_create_response(packet);
char *directory;
DWORD result;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (directory == NULL) {
result = ERROR_INVALID_PARAMETER;
} else {
result = fs_chdir(directory);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}
/*
* Creates a new directory
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
*/
DWORD request_fs_mkdir(Remote * remote, Packet * packet)
{
Packet *response = packet_create_response(packet);
char *directory;
DWORD result;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (directory == NULL) {
result = ERROR_INVALID_PARAMETER;
} else {
result = fs_mkdir(directory);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}
/*
* Removes the supplied directory from disk if it's empty
*
* req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
*/
DWORD request_fs_delete_dir(Remote * remote, Packet * packet)
{
Packet *response = packet_create_response(packet);
char *directory;
DWORD result;
directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
if (directory == NULL) {
result = ERROR_INVALID_PARAMETER;
} else {
result = fs_delete_dir(directory);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}

@ -1,4 +1,6 @@
#include "precomp.h"
#include "fs_local.h"
#include <sys/stat.h>
#include <openssl/md5.h>
@ -23,19 +25,18 @@ static DWORD file_channel_write(Channel *channel, Packet *request,
{
FileContext *ctx = (FileContext *)context;
DWORD result= ERROR_SUCCESS;
DWORD written = 0;
size_t written = 0;
// Write a chunk
if (bufferSize && (written = (DWORD)fwrite(buffer, 1, bufferSize, ctx->fd)) <= 0)
{
written = 0;
result = GetLastError();
if (bufferSize) {
written = fwrite(buffer, 1, bufferSize, ctx->fd);
if (written < bufferSize) {
result = GetLastError();
}
}
// Set bytesWritten
if (bytesWritten)
{
*bytesWritten = written;
if (bytesWritten) {
*bytesWritten = (DWORD)written;
}
return result;
@ -64,18 +65,19 @@ static DWORD file_channel_read(Channel *channel, Packet *request,
{
FileContext *ctx = (FileContext *)context;
DWORD result = ERROR_SUCCESS;
DWORD bytes = 0;
size_t bytes = 0;
// Read a chunk
if (bufferSize && (bytes= (DWORD)fread(buffer, 1, bufferSize, ctx->fd)) <= 0)
{
bytes = 0;
result = GetLastError();
if (bufferSize) {
bytes = fread(buffer, 1, bufferSize, ctx->fd);
if (bytes < bufferSize) {
result = GetLastError();
}
}
// Set bytesRead
if (bytesRead)
*bytesRead = bytes;
if (bytesRead) {
*bytesRead = (DWORD)bytes;
}
return ERROR_SUCCESS;
}
@ -112,8 +114,9 @@ static DWORD file_channel_tell(Channel *channel, Packet *request,
DWORD result = ERROR_SUCCESS;
LONG pos = 0;
if ((pos = ftell(ctx->fd)) < 0)
if ((pos = ftell(ctx->fd)) < 0) {
result = GetLastError();
}
if (offset)
*offset = pos;
@ -136,90 +139,64 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
FileContext *ctx;
LPSTR expandedFilePath = NULL;
do
{
// Allocate a response
response = packet_create_response(packet);
// Allocate a response
response = packet_create_response(packet);
// Get the channel flags
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
// Get the channel flags
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
// Allocate storage for the file context
if (!(ctx = (FileContext *)malloc(sizeof(FileContext))))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Allocate storage for the file context
if (!(ctx = calloc(1, sizeof(FileContext)))) {
res = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
// Get the file path and the mode
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
mode = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
// Get the file path and the mode
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
mode = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
// No file path? bogus.
if (!filePath)
{
res = ERROR_INVALID_PARAMETER;
break;
}
if (mode == NULL) {
mode = "rb";
}
// Expand the file path
if (!(expandedFilePath = fs_expand_path(filePath)))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
}
res = fs_fopen(filePath, mode, &ctx->fd);
if (res != ERROR_SUCCESS) {
goto out;
}
if (!mode)
mode = "rb";
memset(&chops, 0, sizeof(chops));
// Invalid file?
if (!(ctx->fd = fopen(expandedFilePath, mode)))
{
res = GetLastError();
break;
}
// Initialize the pool operation handlers
chops.native.context = ctx;
chops.native.write = file_channel_write;
chops.native.close = file_channel_close;
chops.read = file_channel_read;
chops.eof = file_channel_eof;
chops.seek = file_channel_seek;
chops.tell = file_channel_tell;
memset(&chops, 0, sizeof(chops));
// Check the response allocation & allocate a un-connected
// channel
if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops)))) {
res = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
// Initialize the pool operation handlers
chops.native.context = ctx;
chops.native.write = file_channel_write;
chops.native.close = file_channel_close;
chops.read = file_channel_read;
chops.eof = file_channel_eof;
chops.seek = file_channel_seek;
chops.tell = file_channel_tell;
// Check the response allocation & allocate a un-connected
// channel
if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops))))
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Add the channel identifier to the response
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,
channel_get_id(newChannel));
} while (0);
// Add the channel identifier to the response
packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));
out:
// Transmit the packet if it's valid
packet_transmit_response(res, remote, response);
// Clean up on failure
if (res != ERROR_SUCCESS)
{
if (newChannel)
if (res != ERROR_SUCCESS) {
if (newChannel) {
channel_destroy(newChannel, NULL);
if (ctx)
free(ctx);
}
free(ctx);
}
// Free the expanded file path if it was allocated
if (expandedFilePath)
free(expandedFilePath);
return res;
}
@ -229,20 +206,12 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
DWORD request_fs_separator(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
#ifdef _WIN32
LPCSTR separator = "\\";
#else
LPCSTR separator = "/";
#endif
packet_add_tlv_string(response, TLV_TYPE_STRING, separator);
packet_add_tlv_string(response, TLV_TYPE_STRING, FS_SEPARATOR);
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
return packet_transmit(remote, response, NULL);
}
@ -250,73 +219,62 @@ DWORD request_fs_separator(Remote *remote, Packet *packet)
* Gets information about the file path that is supplied and returns it to the
* requestor
*
* TLVs:
*
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
*/
DWORD request_fs_stat(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
struct meterp_stat buf;
LPCSTR filePath;
LPSTR expanded = NULL;
char *filePath;
char *expanded = NULL;
DWORD result = ERROR_SUCCESS;
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
// Validate parameters
if (!filePath)
if (!filePath) {
result = ERROR_INVALID_PARAMETER;
else if (!(expanded = fs_expand_path(filePath)))
result = ERROR_NOT_ENOUGH_MEMORY;
else
{
result = fs_stat(expanded, &buf);
if (0 == result)
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
sizeof(buf));
goto out;
}
// Set the result and transmit the response
expanded = fs_expand_path(filePath);
if (expanded == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
result = fs_stat(expanded, &buf);
if (0 == result) {
packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
}
free(expanded);
out:
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
if (expanded)
free(expanded);
return result;
return packet_transmit(remote, response, NULL);
}
/*
* Removes the supplied file from disk
*
* TLVs:
*
* req: TLV_TYPE_FILE_PATH - The file that is to be removed.
*/
DWORD request_fs_delete_file(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR path;
char *path;
DWORD result = ERROR_SUCCESS;
path = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
if (!path)
if (!path) {
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!DeleteFile(path))
#else
else if (unlink(path))
#endif
result = GetLastError();
} else {
result = fs_delete_file(path);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
return packet_transmit(remote, response, NULL);
}
/*
@ -328,164 +286,107 @@ DWORD request_fs_file_expand_path(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD result = ERROR_SUCCESS;
LPSTR expanded = NULL;
LPSTR regular;
char *expanded = NULL;
char *regular;
regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
if (regular == NULL) {
result = ERROR_INVALID_PARAMETER;
goto out;
}
do
{
// No regular path?
if (!regular)
{
result = ERROR_INVALID_PARAMETER;
break;
}
// Allocate storage for the expanded path
expanded = fs_expand_path(regular);
if (expanded == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
// Allocate storage for the expanded path
if (!(expanded = fs_expand_path(regular)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
} while (0);
// Transmit the response to the mofo
packet_transmit_response(result, remote, response);
if (expanded)
free(expanded);
return ERROR_SUCCESS;
packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
free(expanded);
out:
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
return packet_transmit(remote, response, NULL);
}
/*
* Returns the MD5 hash for a specified file path
*
* TLVs:
*
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
*/
DWORD request_fs_md5(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR filePath;
LPSTR expanded = NULL;
char *filePath;
DWORD result = ERROR_SUCCESS;
MD5_CTX context;
FILE *fd;
size_t ret;
unsigned char buff[16384];
unsigned char hash[128];
unsigned char hash[MD5_DIGEST_LENGTH + 1] = {0};
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
// Validate parameters
if (!filePath)
result = ERROR_INVALID_PARAMETER;
else if (!(expanded = fs_expand_path(filePath)))
result = ERROR_NOT_ENOUGH_MEMORY;
else
{
do {
MD5_Init(&context);
fd = fopen(expanded, "rb");
if (! fd) {
result = GetLastError();
break;
}
result = fs_fopen(filePath, "rb", &fd);
if (result == ERROR_SUCCESS) {
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
MD5_Update(&context, buff, ret);
}
MD5_Init(&context);
fclose(fd);
MD5_Final(hash, &context);
while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
MD5_Update(&context, buff, ret);
}
// One byte extra for the NULL
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 17);
} while(0);
MD5_Final(hash, &context);
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
fclose(fd);
}
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
if (expanded)
free(expanded);
return ERROR_SUCCESS;
return packet_transmit(remote, response, NULL);
}
/*
* Returns the SHA1 hash for a specified file path
*
* TLVs:
*
* req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
*/
DWORD request_fs_sha1(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCSTR filePath;
LPSTR expanded = NULL;
char *filePath;
DWORD result = ERROR_SUCCESS;
SHA_CTX context;
FILE *fd;
size_t ret;
unsigned char buff[16384];
unsigned char hash[128];
unsigned char hash[SHA_DIGEST_LENGTH + 1] = {0};
filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
// Validate parameters
if (!filePath)
result = ERROR_INVALID_PARAMETER;
else if (!(expanded = fs_expand_path(filePath)))
result = ERROR_NOT_ENOUGH_MEMORY;
else
{
do {
SHA1_Init(&context);
fd = fopen(expanded, "rb");
if (! fd) {
result = GetLastError();
break;
}
result = fs_fopen(filePath, "rb", &fd);
if (result == ERROR_SUCCESS) {
SHA1_Init(&context);
while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
SHA1_Update(&context, buff, ret);
}
while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
SHA1_Update(&context, buff, ret);
}
fclose(fd);
SHA1_Final(hash, &context);
fclose(fd);
SHA1_Final(hash, &context);
// One byte extra for the NULL
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 21);
} while(0);
packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
}
// Set the result and transmit the response
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
if (expanded)
free(expanded);
return ERROR_SUCCESS;
return packet_transmit(remote, response, NULL);
}
/*
* Copies source file path to destination
*
@ -495,25 +396,19 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD result = ERROR_SUCCESS;
LPCSTR oldpath;
LPCSTR newpath;
char *oldpath;
char *newpath;
oldpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_NAME);
newpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
if (!oldpath)
if (!oldpath) {
result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
else if (!MoveFile(oldpath,newpath))
#else
else if (rename(oldpath,newpath))
#endif
result = GetLastError();
} else {
result = fs_move(oldpath, newpath);
}
packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
packet_transmit(remote, response, NULL);
return ERROR_SUCCESS;
return packet_transmit(remote, response, NULL);
}

@ -1,6 +1,8 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
#define _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
#include <stdint.h>
LPSTR fs_expand_path(LPCSTR regular);
/*
@ -25,33 +27,4 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet);
*/
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet);
/*
* Stat structures on Windows and various Unixes are all slightly different.
* Use this as a means of standardization so the client has some hope of
* understanding what the stat'd file really is.
*/
struct meterp_stat {
unsigned int st_dev;
unsigned short st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short pad;
unsigned int st_rdev;
unsigned int st_size;
/*
* These are always 64-bits on Windows and usually 32-bits on Linux. Force
* them to be the same size everywhere.
*/
unsigned long long st_atime;
unsigned long long st_mtime;
unsigned long long st_ctime;
};
int fs_stat(LPCSTR filename, struct meterp_stat *buf);
#endif

@ -0,0 +1,68 @@
#ifndef _FS_LOCAL_H
#define _FS_LOCAL_H
#include <stdint.h>
#include <stdio.h>
#ifdef _WIN32
#define FS_SEPARATOR "\\"
#define FS_MAX_PATH 32768
#else
#define FS_SEPARATOR "/"
#define FS_MAX_PATH PATH_MAX
#endif
/*
* Stat structures on Windows and various Unixes are all slightly different.
* Use this as a means of standardization so the client has some hope of
* understanding what the stat'd file really is.
*/
struct meterp_stat {
uint32_t st_dev;
uint16_t st_ino;
uint16_t st_mode;
uint16_t st_nlink;
uint16_t st_uid;
uint16_t st_gid;
uint16_t pad;
uint32_t st_rdev;
uint32_t st_size;
/*
* These are always 64-bits on Windows and usually 32-bits on Linux. Force
* them to be the same size everywhere.
*/
uint64_t st_atime;
uint64_t st_mtime;
uint64_t st_ctime;
};
typedef void (*fs_ls_cb_t)(void *arg, char *name, char *short_name, char *path);
int fs_chdir(const char *directory);
int fs_delete_dir(const char *directory);
int fs_delete_file(const char *path);
/*
* Returns an expanded file path that must be freed
*/
char * fs_expand_path(const char *regular);
int fs_fopen(const char *path, const char *mode, FILE **f);
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg);
int fs_getwd(char **directory);
int fs_mkdir(const char *directory);
int fs_move(const char *oldpath, const char *newpath);
/*
* Fills the platform-independent meterp_stat buf with data from the
* platform-dependent stat()
*/
int fs_stat(char *filename, struct meterp_stat *buf);
#endif

@ -0,0 +1,126 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "precomp.h"
#include "fs_local.h"
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
{
struct meterp_stat s;
struct dirent *data;
char path[FS_MAX_PATH];
DIR *ctx = opendir(directory);
if (ctx == NULL) {
return errno;
}
while ((data = readdir(ctx))) {
snprintf(path, sizeof(path), "%s/%s", directory, data->d_name);
cb(arg, data->d_name, NULL, path);
}
closedir(ctx);
return ERROR_SUCCESS;
}
int fs_chdir(const char *directory)
{
if (chdir(directory) == -1) {
return errno;
}
return ERROR_SUCCESS;
}
int fs_delete_file(const char *path)
{
if (unlink(path) == -1) {
return errno;
}
return ERROR_SUCCESS;
}
int fs_delete_dir(const char *directory)
{
if (rmdir(directory) == -1) {
return errno;
}
return ERROR_SUCCESS;
}
char * fs_expand_path(const char *regular)
{
return strdup(regular);
}
int fs_getwd(char **directory)
{
char dir[FS_MAX_PATH];
if (getcwd(dir, sizeof(dir)) == NULL) {
return errno;
}
*directory = strdup(dir);
return *directory == NULL ? ERROR_NOT_ENOUGH_MEMORY : ERROR_SUCCESS;
}
int fs_mkdir(const char *directory)
{
if (mkdir(directory, 0777) == -1) {
return errno;
}
return ERROR_SUCCESS;
}
int fs_fopen(const char *path, const char *mode, FILE **f)
{
int rc = 0;
if (path == NULL || f == NULL) {
return ERROR_INVALID_PARAMETER;
}
*f = fopen(path, mode);
if (*f == NULL) {
rc = errno;
}
return rc;
}
int fs_move(const char *oldpath, const char *newpath)
{
if (rename(oldpath, newpath) == -1) {
return errno;
}
return ERROR_SUCCESS;
}
int fs_stat(char *filename, struct meterp_stat *buf)
{
struct stat sbuf;
if (stat(filename, &sbuf) == -1) {
return errno;
}
buf->st_dev = sbuf.st_dev;
buf->st_ino = sbuf.st_ino;
buf->st_mode = sbuf.st_mode;
buf->st_nlink = sbuf.st_nlink;
buf->st_uid = sbuf.st_uid;
buf->st_gid = sbuf.st_gid;
buf->st_rdev = sbuf.st_rdev;
buf->st_size = sbuf.st_size;
buf->st_atime = sbuf.st_atime;
buf->st_mtime = sbuf.st_mtime;
buf->st_ctime = sbuf.st_ctime;
return ERROR_SUCCESS;
}

@ -1,75 +0,0 @@
#include "precomp.h"
#include "fs.h"
#include <sys/stat.h>
/*
* Returns an expanded file path that must be freed
*/
LPSTR fs_expand_path(LPCSTR regular)
{
#ifdef _WIN32
DWORD expandedFilePathSize = 32768;
LPSTR expandedFilePath = NULL;
do
{
// Expand the file path
if (!(expandedFilePath = (LPSTR)malloc(expandedFilePathSize)))
break;
// Expand the file path being accessed
if (!ExpandEnvironmentStrings(regular, expandedFilePath,
expandedFilePathSize - 1))
{
free(expandedFilePath);
expandedFilePath = 0;
break;
}
expandedFilePath[expandedFilePathSize - 1] = 0;
} while (0);
return expandedFilePath;
#else /* Hack to make it work with existing code under *nix */
char *expandedFilePath;
DWORD expandedFilePathSize = strlen(regular)+1;
expandedFilePath = malloc(expandedFilePathSize);
strncpy(expandedFilePath, regular, expandedFilePathSize);
expandedFilePath[expandedFilePathSize - 1] = '\0';
return expandedFilePath;
#endif
}
/*
* Fills the platform-independent meterp_stat buf with data from the platform-dependent stat()
*/
int fs_stat(LPCSTR filename, struct meterp_stat *buf) {
struct stat sbuf;
int ret;
ret = stat(filename, &sbuf);
if (ret == 0) {
buf->st_dev = sbuf.st_dev;
buf->st_ino = sbuf.st_ino;
buf->st_mode = sbuf.st_mode;
buf->st_nlink = sbuf.st_nlink;
buf->st_uid = sbuf.st_uid;
buf->st_gid = sbuf.st_gid;
buf->st_rdev = sbuf.st_rdev;
buf->st_size = sbuf.st_size;
buf->st_atime = (unsigned long long)sbuf.st_atime;
buf->st_mtime = (unsigned long long)sbuf.st_mtime;
buf->st_ctime = (unsigned long long)sbuf.st_ctime;
return 0;
} else {
#ifdef _WIN32
return GetLastError();
#else
return errno;
#endif
}
}

@ -0,0 +1,339 @@
#include <sys/stat.h>
#include "fs_local.h"
#include "precomp.h"
static wchar_t *utf8_to_wchar(const char *in)
{
wchar_t *out;
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in, -1, NULL, 0);
if (len <= 0) {
return NULL;
}
out = calloc(len, sizeof(wchar_t));
if (out == NULL) {
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, 0, in, -1, out, len) == 0) {
free(out);
out = NULL;
}
return out;
}
static char *wchar_to_utf8(const wchar_t *in)
{
char *out;
int len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL);
if (len <= 0) {
return NULL;
}
out = calloc(len, sizeof(char));
if (out == NULL) {
return NULL;
}
if (WideCharToMultiByte(CP_UTF8, 0, in, -1, out, len, NULL, FALSE) == 0) {
free(out);
out = NULL;
}
return out;
}
char * fs_expand_path(const char *regular)
{
wchar_t expanded_path[FS_MAX_PATH];
wchar_t *regular_w;
regular_w = utf8_to_wchar(regular);
if (regular_w == NULL) {
return NULL;
}
if (ExpandEnvironmentStringsW(regular_w, expanded_path, FS_MAX_PATH) == 0) {
free(regular_w);
return NULL;
}
free(regular_w);
return wchar_to_utf8(expanded_path);
}
int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
{
DWORD result = 0;
LPSTR expanded = NULL;
LPSTR baseDirectory = NULL;
char tempDirectory[FS_MAX_PATH];
_snprintf(tempDirectory, sizeof(tempDirectory), "%s", directory);
/*
* If there is not wildcard mask on the directory, create a version of the
* directory with a mask appended
*/
if (strrchr(directory, '*') == NULL) {
_snprintf(tempDirectory, sizeof(tempDirectory), "%s\\*",
directory);
baseDirectory = _strdup(directory);
if (baseDirectory == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
} else {
/*
* Otherwise, if it does have an asterisk, we need to scan back
* and find the base directory. If there is no slash, it means
* we're listing the cwd.
*/
PCHAR slash = strrchr(directory, '\\');
if (slash) {
*slash = 0;
baseDirectory = _strdup(directory);
if (baseDirectory == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
*slash = '\\';
}
}
expanded = fs_expand_path(tempDirectory);
if (expanded == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
WIN32_FIND_DATAW data;
wchar_t *path_w = utf8_to_wchar(expanded);
if (path_w == NULL) {
result = GetLastError();
goto out;
}
HANDLE ctx = FindFirstFileW(path_w, &data);
if (ctx == NULL) {
result = GetLastError();
goto out;
}
do {
if (ctx == INVALID_HANDLE_VALUE) {
result = GetLastError();
break;
}
char *filename = wchar_to_utf8(data.cFileName);
char *short_filename = wchar_to_utf8(data.cAlternateFileName);
char path[FS_MAX_PATH];
if (baseDirectory) {
_snprintf(path, sizeof(path), "%s\\%s", baseDirectory, filename);
} else {
_snprintf(path, sizeof(path), "%s", filename);
}
cb(arg, filename, short_filename, path);
free(filename);
free(short_filename);
} while (FindNextFileW(ctx, &data));
/*
* Clean up resources
*/
FindClose(ctx);
free(expanded);
out:
free(baseDirectory);
free(path_w);
return result;
}
int fs_chdir(const char *directory)
{
int rc = ERROR_SUCCESS;
wchar_t *dir_w = utf8_to_wchar(directory);
if (dir_w == NULL) {
rc = GetLastError();
goto out;
}
if (SetCurrentDirectoryW(dir_w) == 0) {
rc = GetLastError();
}
out:
free(dir_w);
return rc;
}
int fs_delete_dir(const char *directory)
{
int rc = ERROR_SUCCESS;
wchar_t *dir_w = utf8_to_wchar(directory);
if (dir_w == NULL) {
rc = GetLastError();
goto out;
}
if (RemoveDirectoryW(dir_w) == 0) {
rc = GetLastError();
}
out:
free(dir_w);
return rc;
}
int fs_delete_file(const char *path)
{
int rc = ERROR_SUCCESS;
wchar_t *path_w = utf8_to_wchar(path);
if (path_w == NULL) {
rc = GetLastError();
goto out;
}
if (DeleteFileW(path_w) == 0) {
rc = GetLastError();
}
out:
free(path_w);
return rc;
}
int fs_getwd(char **dir)
{
int rc = ERROR_SUCCESS;
wchar_t dir_w[FS_MAX_PATH];
if (GetCurrentDirectoryW(FS_MAX_PATH, dir_w) == 0) {
rc = GetLastError();
goto out;
}
*dir = wchar_to_utf8(dir_w);
if (*dir == NULL) {
rc = GetLastError();
}
out:
return rc;
}
int fs_move(const char *oldpath, const char *newpath)
{
int rc = ERROR_SUCCESS;
wchar_t *old_w = utf8_to_wchar(oldpath);
wchar_t *new_w = utf8_to_wchar(newpath);
if ((old_w == NULL) || (new_w == NULL)) {
rc = GetLastError();
goto out;
}
if (MoveFileW(old_w, new_w) == 0) {
rc = GetLastError();
}
out:
free(old_w);
free(new_w);
return rc;
}
int fs_mkdir(const char *directory)
{
int rc = ERROR_SUCCESS;
wchar_t *dir_w = utf8_to_wchar(directory);
if (dir_w == NULL) {
rc = GetLastError();
goto out;
}
if (CreateDirectoryW(dir_w, NULL) == 0) {
rc = GetLastError();
}
out:
free(dir_w);
return rc;
}
int fs_fopen(const char *path, const char *mode, FILE **f)
{
char *expanded = NULL;
int rc = ERROR_SUCCESS;
if (path == NULL || f == NULL) {
return ERROR_INVALID_PARAMETER;
}
if ((expanded = fs_expand_path(path)) == NULL) {
return ERROR_NOT_ENOUGH_MEMORY;
}
wchar_t *path_w = utf8_to_wchar(expanded);
wchar_t *mode_w = utf8_to_wchar(mode);
if ((path_w == NULL) || (mode_w == NULL)) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto out;
}
*f = _wfopen(path_w, mode_w);
if (*f == NULL) {
rc = GetLastError();
}
out:
free(expanded);
free(path_w);
free(mode_w);
return rc;
}
int fs_stat(char *filename, struct meterp_stat *buf)
{
struct _stat64i32 sbuf;
wchar_t *filename_w = utf8_to_wchar(filename);
if (filename_w == NULL) {
return -1;
}
if (_wstat(filename_w, &sbuf) == -1) {
return GetLastError();
}
free(filename_w);
buf->st_dev = sbuf.st_dev;
buf->st_ino = sbuf.st_ino;
buf->st_mode = sbuf.st_mode;
buf->st_nlink = sbuf.st_nlink;
buf->st_uid = sbuf.st_uid;
buf->st_gid = sbuf.st_gid;
buf->st_rdev = sbuf.st_rdev;
buf->st_size = sbuf.st_size;
buf->st_atime = sbuf.st_atime;
buf->st_mtime = sbuf.st_mtime;
buf->st_ctime = sbuf.st_ctime;
return ERROR_SUCCESS;
}

@ -216,8 +216,16 @@ DWORD DeinitServerExtension(Remote *remote)
* @param bufferSize Size of the \c buffer parameter.
* @return Indication of success or failure.
*/
#ifdef _WIN32
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
#else
DWORD GetExtensionName(char* buffer, int bufferSize)
#endif
{
#ifdef _WIN32
strncpy_s(buffer, bufferSize, "stdapi", bufferSize - 1);
#else
strncpy(buffer, "stdapi", bufferSize - 1);
#endif
return ERROR_SUCCESS;
}

@ -23,6 +23,7 @@
#define TLV_TYPE_FILE_PATH MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1202 )
#define TLV_TYPE_FILE_MODE MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1203 )
#define TLV_TYPE_FILE_SIZE MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 1204 )
#define TLV_TYPE_FILE_SHORT_NAME MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 1205 )
#define TLV_TYPE_STAT_BUF MAKE_CUSTOM_TLV( TLV_META_TYPE_COMPLEX, TLV_TYPE_EXTENSION_STDAPI, 1220 )

@ -2,6 +2,7 @@
#include "metsrv.h"
extern Command *extensionCommands;
extern PLIST gExtensionList;
DWORD request_core_loadlib(Remote *remote, Packet *packet)
{
@ -61,15 +62,37 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
// call its Init routine
if (flags & LOAD_LIBRARY_FLAG_EXTENSION)
{
DWORD(*init)(Remote *remote);
PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
if (!pExtension)
{
res = ERROR_NOT_ENOUGH_MEMORY;
break;
}
//DWORD(*init)(Remote *remote);
pExtension->init = dlsym(library, "InitServerExtension");
init = dlsym(library, "InitServerExtension");
// Call the init routine in the library
if (init)
if (pExtension->init)
{
dprintf("calling InitServerExtension");
res = init(remote);
res = pExtension->init(remote);
pExtension->getname = dlsym(library, "GetExtensionName");
pExtension->deinit = dlsym(library, "DeinitServerExtension");
if (pExtension->getname)
{
pExtension->getname(pExtension->name, sizeof(pExtension->name));
}
list_push(gExtensionList, pExtension);
}
else
{
free(pExtension);
}
if (response)
{
for (command = extensionCommands; command != first; command = command->next)

@ -7,6 +7,8 @@ extern HINSTANCE hAppInstance;
PLIST gExtensionList = NULL;
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket);
// Dispatch table
Command customCommands[] =
{
@ -15,6 +17,56 @@ Command customCommands[] =
COMMAND_TERMINATOR
};
typedef struct _EnumExtensions
{
Packet* pResponse;
char* lpExtensionName;
} EnumExtensions, * PEnumExtensions;
BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
{
PEnumExtensions pEnum = (PEnumExtensions)pState;
Command* command = NULL;
if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
{
PEXTENSION pExt = (PEXTENSION)pData;
if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
{
dprintf("[LISTEXT] Found extension: %s", pExt->name);
for (command = pExt->start; command != pExt->end; command = command->next)
{
packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
}
return TRUE;
}
}
return FALSE;
}
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
{
BOOL bResult = FALSE;
Packet* pResponse = packet_create_response(pPacket);
if (pResponse != NULL)
{
EnumExtensions enumExt;
enumExt.pResponse = pResponse;
enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
// Start by enumerating the names of the extensions
bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
packet_transmit(pRemote, pResponse, NULL);
}
return ERROR_SUCCESS;
}
/*
* Registers custom command handlers
*/
@ -38,7 +90,10 @@ VOID deregister_dispatch_routines(Remote * remote)
break;
}
extension->deinit(remote);
if (extension->deinit)
{
extension->deinit(remote);
}
free(extension);
}

@ -8,54 +8,6 @@ extern PLIST gExtensionList;
// see common/base.c
extern Command *extensionCommands;
typedef struct _EnumExtensions
{
Packet* pResponse;
char* lpExtensionName;
} EnumExtensions, * PEnumExtensions;
BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
{
PEnumExtensions pEnum = (PEnumExtensions)pState;
if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
{
PEXTENSION pExt = (PEXTENSION)pData;
if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
{
dprintf("[LISTEXT] Found extension: %s", pExt->name);
for (Command* command = pExt->start; command != pExt->end; command = command->next)
{
packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
}
return TRUE;
}
}
return FALSE;
}
DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
{
Packet* pResponse = packet_create_response(pPacket);
if (pResponse != NULL)
{
EnumExtensions enumExt;
enumExt.pResponse = pResponse;
enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
// Start by enumerating the names of the extensions
BOOL bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
packet_transmit(pRemote, pResponse, NULL);
}
return ERROR_SUCCESS;
}
DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand)
{
DWORD dwResult = ERROR_OUTOFMEMORY;
@ -129,6 +81,8 @@ DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote*
return dwResult;
}
/*
* core_loadlib
* ------------

@ -9,7 +9,7 @@ CFLAGS+= -I../../source/extensions/stdapi/server
objects = \
server/fs/dir.o \
server/fs/file.o \
server/fs/fs_util.o \
server/fs/fs_posix.o \
server/general.o \
server/net/config/interface.o \
server/net/config/route.o \

@ -633,7 +633,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
</ClCompile>
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\dir.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\file.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_util.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_win.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\fs\search.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\net\net.c" />
<ClCompile Include="..\..\source\extensions\stdapi\server\net\config\interface.c" />
@ -687,6 +687,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
<ClInclude Include="..\..\source\extensions\stdapi\server\webcam\bmp2jpeg.h" />
<ClInclude Include="..\..\source\extensions\stdapi\server\webcam\webcam.h" />
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs.h" />
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs_local.h" />
<ClInclude Include="..\..\source\extensions\stdapi\server\fs\search.h" />
</ItemGroup>
<ItemGroup>
@ -714,4 +715,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>
</Project>