@@ -0,0 +1 @@ | |||
ü�ÎÒÇW½�ƒöw³„9Éø“(,‡òe㮺ϓ¹>ôb¹ñn�fǘªiè`ûêõ,:}2ªy£O–¾þ˜G8fÿÝ)B÷qFøR$aäu*†�bDêt¼FÃ\^iŸhŠ'ðÑ”;×1çȳ©=t`˜µÁm&ÿ™¶òè“ùå�3m¹±G |
@@ -0,0 +1 @@ | |||
5}2¾tè‘�CDšM&B5Õ£Ün1�DÂ( kŸL_cÖÇ |
@@ -0,0 +1 @@ | |||
ΒΪσΚ\…«ILΚ_ρ�Πόr$@°b:�_½¨σϋ!+]Γ?nNm |
@@ -0,0 +1,4 @@ | |||
#include "../inc/lc6_common.h" | |||
char* lc6bootstrap_getip(LC6_BOOTSTRAP *bs); |
@@ -5,6 +5,13 @@ | |||
#include <arpa/inet.h> | |||
#include "../inc/libchat6.h" | |||
#include "../inc/lc6_helpers.h" | |||
#ifdef LC6_DEBUG | |||
#define malloc(x) lc6helpers_malloc(x, __FILE__, __func__, __LINE__) | |||
#define realloc(x,y) lc6helpers_realloc(x, y, __FILE__, __func__, __LINE__) | |||
#define free(x) lc6helpers_free(x, __FILE__, __func__, __LINE__) | |||
#endif | |||
typedef struct LC6_NODE { | |||
unsigned char *pub_key; | |||
@@ -17,30 +24,38 @@ typedef struct LC6_USER { | |||
unsigned char nickname[256]; | |||
unsigned char pub_key[32]; | |||
unsigned char priv_key[32]; | |||
unsigned char icon[32768]; | |||
unsigned int status; | |||
uint8_t status; | |||
} LC6_USER; | |||
typedef struct LC6_FRIEND { | |||
struct LC6_FRIEND *prev; | |||
struct LC6_FRIEND *next; | |||
unsigned char nickname[256]; | |||
unsigned char pub_key[32]; | |||
uint8_t status; | |||
} LC6_FRIEND; | |||
#define LC6_CONFIG_BOOTSTRAP "bootstrap.bin" | |||
#define LC6_CONFIG_USER "user.bin" | |||
#define LC6_CONFIG_FRIENDS "friends.bin" | |||
#define LC6_CONFIG_FRIEND "friends.bin" | |||
#define LC6_CONFIG_MAXLEN 50 | |||
typedef struct LC6_BOOTSTRAP { | |||
struct LC6_BOOTSTRAP *prev; | |||
struct LC6_BOOTSTRAP *next; | |||
time_t last_contact; | |||
int af; | |||
uint64_t last_contact; | |||
uint8_t af; | |||
union addr { | |||
struct in_addr inet; | |||
struct in6_addr inet6; | |||
uint32_t inet; | |||
unsigned char inet6[16]; | |||
} addr; | |||
} LC6_BOOTSTRAP; | |||
typedef struct LC6_CTX { | |||
char path[MAXPATHLEN]; | |||
char path[MAXPATHLEN-LC6_CONFIG_MAXLEN]; | |||
LC6_USER *user; | |||
LC6_USER *node; | |||
LC6_USER *friends; | |||
LC6_FRIEND *friend; | |||
LC6_BOOTSTRAP *bootstrap; | |||
} LC6_CTX; | |||
@@ -13,4 +13,6 @@ void lc6config_load_file( | |||
char *filename, | |||
unsigned char *password); | |||
void lc6config_bootstrap_add(LC6_CTX *conf, LC6_BOOTSTRAP *bs); | |||
#endif |
@@ -3,6 +3,8 @@ | |||
#include "../inc/lc6_common.h" | |||
int lc6crypto_init(void); | |||
int lc6crypto_public_encrypt( | |||
const unsigned char *data, | |||
const int data_len, |
@@ -1,9 +1,14 @@ | |||
#ifndef LC6_HELPERS_H | |||
#define LC6_HELPERS_H | |||
#include "../inc/lc6_common.h" | |||
// DO NOT include the common.h here. | |||
// because we're overriding functions | |||
// #include "../inc/lc6_common.h" | |||
void lc6helpers_printhex(unsigned char*, int); | |||
void lc6helpers_banner(unsigned char*); | |||
void lc6helpers_printhex(unsigned char*, int); | |||
void lc6helpers_banner(unsigned char*); | |||
void* lc6helpers_malloc(size_t, char *, const char*, int); | |||
void* lc6helpers_realloc(void *ptr, size_t, char *, const char*, int); | |||
void lc6helpers_free(void *ptr, char *, const char*, int); | |||
#endif |
@@ -0,0 +1,9 @@ | |||
#ifndef LC6_TIME_H | |||
#define LC6_TIME_H | |||
#include "../inc/lc6_common.h" | |||
time_t lc6time_get(void); | |||
#endif |
@@ -16,7 +16,7 @@ | |||
CC := gcc | |||
#CCFLAGS := -fPIC -Wall -Werror -std=c11 -pedantic -O2 | |||
CCFLAGS := -fPIC -Wall -Werror -std=c11 -pedantic -g | |||
CCFLAGS := -DLC6_DEBUG -fPIC -Wall -Werror -std=c11 -pedantic -g | |||
LDFLAGS := | |||
LIBS := -lchat6 -lssl -lpthread -lcrypto -lsodium | |||
@@ -26,6 +26,8 @@ LIBDIR := ../lib | |||
TARGETS:= $(LIBDIR)/libchat6.so $(LIBDIR)/libchat6.a | |||
MAINS := $(.o, $(TARGETS) ) | |||
OBJ := \ | |||
lc6_bootstrap.o \ | |||
lc6_time.o \ | |||
lc6_node.o \ | |||
lc6_config.o \ | |||
lc6_helpers.o \ | |||
@@ -36,15 +38,14 @@ OBJ := \ | |||
$(MAINS) | |||
DEPS := | |||
.PHONY: all clean install uninstall test | |||
help: | |||
@echo "make <all|clean|install|uninstall|test>" | |||
.PHONY: all clean test bootstrap | |||
all: $(TARGETS) | |||
clean: | |||
rm -f $(TARGETS) $(OBJ) $(BINDIR)/test test.o | |||
rm -f $(TARGETS) $(OBJ) | |||
rm -f $(BINDIR)/test test.o | |||
rm -f $(BINDIR)/bootstrap bootstrap.o | |||
$(OBJ) : %.o : %.c | |||
$(CC) $(CCFLAGS) $< -c -o $@ |
@@ -1,15 +1,85 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <assert.h> | |||
#include <arpa/inet.h> | |||
#include "../inc/lc6_config.h" | |||
#include "../inc/lc6_time.h" | |||
#include "../inc/lc6_bootstrap.h" | |||
const char bootlist[4][50] = { | |||
"127.0.0.1", | |||
"2001:1a8f:ffff::abcd", | |||
"blah blah blah lol", | |||
"yep: not working ;-)" | |||
}; | |||
int main(int argc, char **argv) { | |||
LC6_CTX *conf = NULL; | |||
if ( argc == 2 ) { | |||
int i = 0;; | |||
printf("Loading configuration files...\n"); | |||
conf = lc6config_load(argv[1], ""); | |||
for(i=0; i<sizeof(bootlist)/sizeof(bootlist[0]); i++) { | |||
char *str = NULL; | |||
struct in_addr addr; | |||
struct in6_addr addr6; | |||
LC6_BOOTSTRAP *bs = malloc(sizeof(LC6_BOOTSTRAP)); | |||
assert(bs); | |||
memset(bs, '\0', sizeof(LC6_BOOTSTRAP)); | |||
printf("Parsing potential IP address '%s'\n", bootlist[i]); | |||
bs->prev = NULL; | |||
bs->next = NULL; | |||
bs->last_contact = lc6time_get(); | |||
printf("Decoding... "); | |||
if ( inet_pton(AF_INET, bootlist[i], &addr) == 1 ) { | |||
printf("IPv4\n"); | |||
bs->af = 4; | |||
bs->addr.inet = addr.s_addr; | |||
} | |||
else if ( inet_pton(AF_INET6, bootlist[i], &addr6) == 1) { | |||
printf("IPv6\n"); | |||
bs->af = 6; | |||
memcpy(bs->addr.inet6, &addr6, sizeof(bs->addr.inet6)); | |||
} | |||
else { | |||
printf("Failed\n"); | |||
free(bs); | |||
bs = NULL; | |||
} | |||
str = lc6bootstrap_getip(bs); | |||
printf("The result is : %s\n", str ? str : "NULL"); | |||
if ( str ) | |||
free(str); | |||
if ( bs ) | |||
lc6config_bootstrap_add(conf, bs); | |||
} | |||
lc6config_save(conf, ""); | |||
lc6config_free(conf); | |||
} | |||
else { | |||
fprintf(stderr,"\ | |||
This is a helper programm for libchat6.\n\ | |||
It will initialise a bootstrap.bin configuration file\n\ | |||
containing a list of bootstrap clients hardcoded at the top of\n\ | |||
bootstrap.c. The default password for the bootstrap.bin file\n\ | |||
is an empty string.\n\n"); | |||
fprintf(stderr,"Usage: %s <path to config dir>\n", argv[0]); | |||
return -1; | |||
} |
@@ -0,0 +1,29 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <arpa/inet.h> | |||
#include <assert.h> | |||
#include <string.h> | |||
#include "../inc/lc6_bootstrap.h" | |||
char* lc6bootstrap_getip(LC6_BOOTSTRAP *bs) { | |||
char *str = NULL; | |||
if ( !bs ) | |||
return NULL; | |||
if ( bs->af == 4 ) { | |||
str = malloc(INET_ADDRSTRLEN); | |||
assert(str); | |||
memset(str, 0, INET_ADDRSTRLEN); | |||
inet_ntop(AF_INET, &bs->addr.inet, str, INET_ADDRSTRLEN); | |||
} | |||
else if ( bs->af == 6 ) { | |||
str = malloc(INET6_ADDRSTRLEN); | |||
assert(str); | |||
memset(str, 0, INET6_ADDRSTRLEN); | |||
inet_ntop(AF_INET6, &bs->addr.inet6, str, INET6_ADDRSTRLEN); | |||
} | |||
return str; | |||
} |
@@ -15,7 +15,7 @@ LC6_CTX* lc6config_load(char *path, unsigned char *password) { | |||
lc6config_load_file(conf, path, LC6_CONFIG_BOOTSTRAP, password); | |||
lc6config_load_file(conf, path, LC6_CONFIG_USER, password); | |||
lc6config_load_file(conf, path, LC6_CONFIG_FRIENDS, password); | |||
lc6config_load_file(conf, path, LC6_CONFIG_FRIEND, password); | |||
// complete defaults | |||
@@ -33,12 +33,12 @@ LC6_CTX* lc6config_load(char *path, unsigned char *password) { | |||
// conf->user may stay NULL | |||
// conf->friends maybe you're all alone, that's ok tho. | |||
// conf->friend maybe you're all alone, that's ok tho. | |||
// conf->bootstrap | |||
// this is a major issue if we can't bootstrap | |||
if ( !conf->bootstrap ) | |||
return NULL; | |||
// if we can't bootstrap, we can't connect to the network | |||
// if ( !conf->bootstrap ) | |||
// return NULL; | |||
return conf; | |||
} | |||
@@ -83,22 +83,25 @@ void lc6config_load_file( | |||
} | |||
} | |||
else if ( strcmp(filename, LC6_CONFIG_USER) == 0 ) { | |||
conf->user = (LC6_USER*)data; | |||
LC6_USER *user = malloc(sizeof(LC6_USER)); | |||
assert(user); | |||
memcpy(user, data, sizeof(LC6_USER)); | |||
conf->user = user; | |||
} | |||
else if ( strcmp(filename, LC6_CONFIG_FRIENDS) == 0 ) { | |||
LC6_USER *prev = NULL; | |||
LC6_USER *chain = (LC6_USER*)data; | |||
else if ( strcmp(filename, LC6_CONFIG_FRIEND) == 0 ) { | |||
LC6_FRIEND *prev = NULL; | |||
LC6_FRIEND *chain = (LC6_FRIEND*)data; | |||
int offset = 0; | |||
while(offset<data_len/sizeof(LC6_USER)) { | |||
LC6_USER *node = malloc(sizeof(LC6_USER)); | |||
while(offset<data_len/sizeof(LC6_FRIEND)) { | |||
LC6_FRIEND *node = malloc(sizeof(LC6_FRIEND)); | |||
assert(node); | |||
memset(node, '\0', sizeof(LC6_USER)); | |||
memcpy(node, chain+offset, sizeof(LC6_USER)); | |||
memset(node, '\0', sizeof(LC6_FRIEND)); | |||
memcpy(node, chain+offset, sizeof(LC6_FRIEND)); | |||
if ( ! prev ) | |||
conf->user = node; | |||
conf->friend = node; | |||
else | |||
prev->next = node; | |||
@@ -109,11 +112,129 @@ void lc6config_load_file( | |||
offset++; | |||
} | |||
} | |||
free(data); | |||
} | |||
void lc6config_bootstrap_add(LC6_CTX *conf, LC6_BOOTSTRAP *bs) { | |||
assert(conf); | |||
assert(bs); | |||
if ( conf->bootstrap ) | |||
conf->bootstrap->prev = bs; | |||
bs->prev = NULL; | |||
bs->next = conf->bootstrap; | |||
conf->bootstrap = bs; | |||
} | |||
void lc6config_free(LC6_CTX *conf) { | |||
LC6_BOOTSTRAP *bnode = conf->bootstrap; | |||
LC6_USER *unode = conf->user; | |||
LC6_FRIEND *fnode = conf->friend; | |||
while(bnode) { | |||
LC6_BOOTSTRAP *next = bnode->next; | |||
free(bnode); | |||
bnode=next; | |||
} | |||
while(unode) { | |||
LC6_USER *next = unode->next; | |||
free(unode); | |||
unode=next; | |||
} | |||
while(fnode) { | |||
LC6_FRIEND *next = fnode->next; | |||
free(fnode); | |||
fnode=next; | |||
} | |||
if ( conf->node ) | |||
free(conf->node); | |||
free(conf); | |||
} | |||
int lc6config_save(LC6_CTX *conf, unsigned char *password) { | |||
LC6_BOOTSTRAP *bootstrap_save = NULL; | |||
LC6_BOOTSTRAP *bootstrap_node = conf->bootstrap; | |||
int bootstrap_len = 0; | |||
LC6_USER *user_save = NULL; | |||
LC6_USER *user_node = conf->user; | |||
int user_len = 0; | |||
LC6_FRIEND *friend_save = NULL; | |||
LC6_FRIEND *friend_node = conf->friend; | |||
int friend_len = 0; | |||
int i; | |||
char file[MAXPATHLEN]; | |||
while(bootstrap_node) { | |||
bootstrap_len++; | |||
bootstrap_node = bootstrap_node->next; | |||
} | |||
bootstrap_node = conf->bootstrap; | |||
bootstrap_save = malloc(sizeof(LC6_BOOTSTRAP)*bootstrap_len); | |||
assert(bootstrap_save); | |||
memset(bootstrap_save, '\0', sizeof(LC6_BOOTSTRAP)*bootstrap_len); | |||
for(i=0; i<bootstrap_len; i++) { | |||
memcpy(bootstrap_save + i, bootstrap_node, sizeof(LC6_BOOTSTRAP)); | |||
(bootstrap_save+i)->prev = NULL; | |||
(bootstrap_save+i)->next = NULL; | |||
bootstrap_node = bootstrap_node->next; | |||
} | |||
snprintf(file, sizeof(file), "%s/%s", conf->path, LC6_CONFIG_BOOTSTRAP); | |||
lc6crypto_writefile(file, password, (unsigned char*)bootstrap_save, bootstrap_len * sizeof(LC6_BOOTSTRAP)); | |||
free(bootstrap_save); | |||
while(user_node) { | |||
user_len++; | |||
user_node = user_node->next; | |||
} | |||
user_save = malloc(sizeof(LC6_USER)*user_len); | |||
assert(user_save); | |||
memset(user_save, 0, sizeof(LC6_USER)*user_len); | |||
for(i=0; i<user_len; i++) { | |||
LC6_USER *node = conf->user + i; | |||
memcpy(user_save + i, node, sizeof(LC6_USER)); | |||
(user_save+i)->prev = NULL; | |||
(user_save+i)->next = NULL; | |||
} | |||
snprintf(file, sizeof(file), "%s/%s", conf->path, LC6_CONFIG_USER); | |||
lc6crypto_writefile(file, password, (unsigned char*)user_save, user_len * sizeof(LC6_USER)); | |||
free(user_save); | |||
while(friend_node) { | |||
friend_len++; | |||
friend_node = friend_node->next; | |||
} | |||
friend_save = malloc(sizeof(LC6_FRIEND)*friend_len); | |||
assert(friend_save); | |||
memset(friend_save, 0, sizeof(LC6_FRIEND)*friend_len); | |||
for(i=0; i<friend_len; i++) { | |||
LC6_FRIEND *node = conf->friend + i; | |||
memcpy(friend_save + i, node, sizeof(LC6_FRIEND)); | |||
(friend_save+i)->prev = NULL; | |||
(friend_save+i)->next = NULL; | |||
} | |||
snprintf(file, sizeof(file), "%s/%s", conf->path, LC6_CONFIG_FRIEND); | |||
lc6crypto_writefile(file, password, (unsigned char*)friend_save, friend_len * sizeof(LC6_FRIEND)); | |||
free(friend_save); | |||
return 1; | |||
} |
@@ -3,9 +3,15 @@ | |||
#include <assert.h> | |||
#include "../inc/lc6_crypto.h" | |||
#include "../inc/lc6_helpers.h" | |||
int lc6crypto_seeded = 0; | |||
int lc6crypto_init(void) { | |||
return sodium_init(); | |||
} | |||
LC6_USER* lc6crypto_genuserkey(LC6_USER *user) { | |||
assert(user); | |||
crypto_box_keypair(user->pub_key, user->priv_key); | |||
@@ -85,21 +91,21 @@ int lc6crypto_readfile( | |||
int *data_len) | |||
{ | |||
FILE *fh; | |||
unsigned char hash[crypto_generichash_BYTES]; | |||
unsigned char *encrypted; | |||
unsigned char key[crypto_secretbox_KEYBYTES]; | |||
unsigned char *encrypted = NULL; | |||
size_t total = 0; | |||
crypto_generichash(hash, sizeof hash, password, strlen((char*)password), NULL, 0); | |||
crypto_generichash(key, sizeof(key), password, strlen((char*)password), NULL, 0); | |||
if ( ( fh = fopen(file, "r") ) == NULL ) | |||
return -1; | |||
while(1) { | |||
unsigned char buf[4096]; | |||
size_t len; | |||
len = fread(buf, sizeof(buf), 1, fh); | |||
size_t len = 0; | |||
len = fread(buf, 1, sizeof(buf), fh); | |||
if ( len == 0 && !feof(fh) ) { | |||
if ( len == 0 && feof(fh) ) { | |||
fclose(fh); | |||
if ( encrypted ) | |||
free(encrypted); | |||
@@ -124,7 +130,7 @@ int lc6crypto_readfile( | |||
assert(*data); | |||
memset(*data, '\0', total - crypto_secretbox_NONCEBYTES); | |||
if (crypto_secretbox_open_easy(*data, encrypted + crypto_secretbox_NONCEBYTES, *data_len, encrypted, hash) != 0) { | |||
if (crypto_secretbox_open_easy(*data, encrypted + crypto_secretbox_NONCEBYTES, *data_len, encrypted, key) != 0) { | |||
free(encrypted); | |||
free(*data); | |||
return -1; | |||
@@ -141,32 +147,33 @@ int lc6crypto_writefile( | |||
const unsigned char *data, | |||
const int data_len) | |||
{ | |||
FILE *fh; | |||
unsigned char hash[crypto_generichash_BYTES]; | |||
unsigned char nonce[crypto_secretbox_NONCEBYTES]; | |||
unsigned char *encrypted; | |||
int offset = 0; | |||
crypto_generichash(hash, sizeof hash, password, strlen((char*)password), NULL, 0); | |||
encrypted = malloc(data_len + crypto_secretbox_NONCEBYTES); | |||
FILE *fh = NULL; | |||
unsigned char key[crypto_secretbox_KEYBYTES] = {0}; | |||
unsigned char nonce[crypto_secretbox_NONCEBYTES] = {0}; | |||
unsigned char *encrypted = NULL; | |||
int total_len = data_len + crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES; | |||
crypto_generichash(key, sizeof(key), password, strlen((char*)password), NULL, 0); | |||
randombytes_buf(nonce, sizeof(nonce)); | |||
encrypted = malloc(total_len); | |||
assert(encrypted); | |||
memset(encrypted, '\0', total_len); | |||
memcpy(encrypted, nonce, crypto_secretbox_NONCEBYTES); | |||
crypto_secretbox_easy(encrypted + crypto_secretbox_NONCEBYTES, data, data_len, nonce, hash); | |||
crypto_secretbox_easy(encrypted + crypto_secretbox_NONCEBYTES, data, data_len, nonce, key); | |||
if ( ( fh = fopen(file, "w") ) == NULL ) | |||
return -1; | |||
if ( fwrite(encrypted + crypto_secretbox_NONCEBYTES + offset, data_len + crypto_secretbox_NONCEBYTES, 1, fh) != 1 ) { | |||
if ( fwrite(encrypted, total_len, 1, fh) != 1 ) { | |||
free(encrypted); | |||
fclose(fh); | |||
return -1; | |||
} | |||
fclose(fh); | |||
free(encrypted); | |||
return 0; | |||
} | |||
@@ -1,4 +1,7 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include "../inc/lc6_helpers.h" | |||
void lc6helpers_printhex(unsigned char *data, int data_len) { | |||
@@ -17,3 +20,22 @@ void lc6helpers_banner(unsigned char *str) { | |||
printf("################################################\n"); | |||
printf("\n"); | |||
} | |||
#ifdef LC6_DEBUG | |||
void* lc6helpers_malloc(size_t size, char *file, const char *func, int line) { | |||
printf("[%s:%d] %s called malloc(%lu)\n", file, line, func, size); | |||
return malloc(size); | |||
} | |||
void* lc6helpers_realloc(void *ptr, size_t size, char *file, const char *func, int line) { | |||
printf("[%s:%d] %s called realloc(%p, %lu)\n", file, line, func, ptr, size); | |||
return realloc(ptr, size); | |||
} | |||
void lc6helpers_free(void *ptr, char *file, const char *func, int line) { | |||
printf("[%s:%d] %s called free(%p)\n", file, line, func, ptr); | |||
free(ptr); | |||
} | |||
#endif |
@@ -0,0 +1,8 @@ | |||
#include <time.h> | |||
#include "../inc/lc6_time.h" | |||
time_t lc6time_get(void) { | |||
return time(NULL); | |||
} |
@@ -1,5 +1,6 @@ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <assert.h> | |||
#include "../inc/lc6_crypto.h" | |||
#include "../inc/lc6_user.h" | |||
@@ -12,6 +13,8 @@ LC6_USER* lc6user_create(void) { | |||
} | |||
void lc6user_free(LC6_CTX *conf, LC6_USER *user) { | |||
assert(conf); | |||
if ( !user ) | |||
return; | |||
@@ -24,8 +27,5 @@ void lc6user_free(LC6_CTX *conf, LC6_USER *user) { | |||
if ( conf->user == user ) | |||
conf->user = user->next; | |||
if ( conf->friends == user ) | |||
conf->friends = user->next; | |||
free(user); | |||
} |
@@ -5,10 +5,14 @@ | |||
#include "../inc/lc6_config.h" | |||
#include "../inc/lc6_user.h" | |||
#include "../inc/lc6_crypto.h" | |||
LIBCHAT* libchat_init(char *path, unsigned char *password) { | |||
LC6_CTX *conf; | |||
LC6_CTX *conf = lc6config_load(path, password); | |||
lc6crypto_init(); | |||
conf = lc6config_load(path, password); | |||
if ( !conf ) | |||
return NULL; |