From 70317df2b54f61b5247a96b659210a5d46d3df1e Mon Sep 17 00:00:00 2001 From: seantywork Date: Tue, 18 Feb 2025 16:19:21 +0900 Subject: [PATCH] add: skeleton --- .gitattributes | 11 + .gitignore | 13 + Makefile | 93 +++ README.md | 4 +- cmd/cli/main.c | 0 cmd/rat-chat/main.c | 41 ++ config.json | 9 + include/rat-chat/core.h | 298 +++++++++ include/rat-chat/front/core.h | 36 ++ include/rat-chat/sock/core.h | 22 + include/rat-chat/utils.h | 33 + src/core.c | 1095 +++++++++++++++++++++++++++++++++ src/hubfront/core.c | 450 ++++++++++++++ src/hubsock/core.c | 513 +++++++++++++++ src/utils.c | 250 ++++++++ tls/ca.crt | 30 + tls/list.txt | 4 + tls/sub.crt | 28 + tls/sub.csr | 26 + vendor/.gitignore | 2 + vendor/README.md | 0 21 files changed, 2957 insertions(+), 1 deletion(-) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 cmd/cli/main.c create mode 100644 cmd/rat-chat/main.c create mode 100644 config.json create mode 100644 include/rat-chat/core.h create mode 100644 include/rat-chat/front/core.h create mode 100644 include/rat-chat/sock/core.h create mode 100644 include/rat-chat/utils.h create mode 100644 src/core.c create mode 100644 src/hubfront/core.c create mode 100644 src/hubsock/core.c create mode 100644 src/utils.c create mode 100644 tls/ca.crt create mode 100644 tls/list.txt create mode 100644 tls/sub.crt create mode 100644 tls/sub.csr create mode 100644 vendor/.gitignore create mode 100644 vendor/README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3ccf886 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +*.html linguist-vendored +*.css linguist-vendored +*.hpp linguist-vendored +*.py linguist-vendored +*.js linguist-vendored +*.go linguist-vendored +*.c linguist-vendored=false +*.h linguist-vendored=false +*.cc linguist-vendored +*.rs linguist-vendored +*.sh linguist-vendored=false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..067b105 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.o +*.out +*.so +*.a +*.run +*.cmd +*.ko +*.mod +*.symvers +*.order +*.mod.c +.vscode +*.pem diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1bcd41c --- /dev/null +++ b/Makefile @@ -0,0 +1,93 @@ + + +GCC_DEV_FLAGS := -Wall -g + +GCC_REL_FLAGS := -Wall + +GCC_OBJ_FLAGS := -Wall -c + +DEP_PACKAGES := libssl-dev + +DEP_MONGOOSE := git clone https://github.com/seantywork/mongoose.git + +DEP_CJSON := git clone https://github.com/seantywork/cJSON.git + +INCLUDES := -I./include -I./vendor + +LIBS := -lpthread -lssl -lcrypto + + +OBJS := core.o +OBJS += utils.o +OBJS += sock.o +OBJS += front.o + +DEP_OBJS := mongoose.o +DEP_OBJS += cJSON.o + + +all: + + @echo "rat-chat: dev, release" + + +deps: + + apt-get update + + apt-get -y install $(DEP_PACKAGES) + +.PHONY: vendor +vendor: + + cd vendor && rm -rf mongoose && $(DEP_MONGOOSE) + + cd vendor && rm -rf cJSON && $(DEP_CJSON) + + +dev: $(OBJS) $(DEP_OBJS) + + gcc $(GCC_DEV_FLAGS) $(INCLUDES) -o rat-chat.out cmd/rat-chat/main.c $(OBJS) $(DEP_OBJS) $(LIBS) + + +release: $(OBJS) $(DEP_OBJS) + + gcc $(GCC_REL_FLAGS) $(INCLUDES) -o rat-chat.out cmd/rat-chat/main.c $(OBJS) $(DEP_OBJS) $(LIBS) + + + + +core.o: + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o core.o src/core.c + + +utils.o: + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o utils.o src/utils.c + +sock.o: + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o sock.o src/hubsock/core.c + +front.o: + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o front.o src/hubfront/core.c + + +mongoose.o: + + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o mongoose.o vendor/mongoose/mongoose.c + +cJSON.o: + + gcc $(GCC_OBJ_FLAGS) $(INCLUDES) -o cJSON.o vendor/cJSON/cJSON.c + + + + +clean: + + rm -rf *.o *.out *.txt + diff --git a/README.md b/README.md index a84b966..77d8c99 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# frankc +# rat-chat + +a dumb way to share linux system info, excute commands, and ... also chat \ No newline at end of file diff --git a/cmd/cli/main.c b/cmd/cli/main.c new file mode 100644 index 0000000..e69de29 diff --git a/cmd/rat-chat/main.c b/cmd/rat-chat/main.c new file mode 100644 index 0000000..6c3a564 --- /dev/null +++ b/cmd/rat-chat/main.c @@ -0,0 +1,41 @@ + +#include "rat-chat/sock/core.h" +#include "rat-chat/front/core.h" + +#include "rat-chat/utils.h" +FILE* LOGFP; + +pthread_mutex_t G_MTX; + +int main(){ + + + srand((unsigned int)time(NULL)); + + LOGFP = fopen("log.txt","a"); + + + pthread_t sock_tid; + pthread_t front_tid; + + if (pthread_mutex_init(&G_MTX, NULL) != 0) { + printf("mutex init has failed\n"); + return -1; + } + + + pthread_create(&front_tid, NULL, (void*)front_listen_and_serve, NULL); + + sleepms(500); + + pthread_create(&sock_tid, NULL, (void*)sock_listen_and_serve, NULL); + + sleepms(500); + + + pthread_join(front_tid, NULL); + + fclose(LOGFP); + + +} \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..d291df5 --- /dev/null +++ b/config.json @@ -0,0 +1,9 @@ +{ + "users":[ + { + "id": "seantywork@gmail.com", + "pw": "hackme" + } + ] + +} diff --git a/include/rat-chat/core.h b/include/rat-chat/core.h new file mode 100644 index 0000000..70f851f --- /dev/null +++ b/include/rat-chat/core.h @@ -0,0 +1,298 @@ +#ifndef _FRANK_HUB_H_ +#define _FRANK_HUB_H_ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// ep headers +#include +#include +#include +#include +// ssl headers +#include +#include +#include + +#include "mongoose/mongoose.h" +#include "cJSON/cJSON.h" + +#define DEBUG_THIS 0 + +#define HUB_WORD 8 +#define HUB_HEADER_BYTELEN HUB_WORD * 3 +#define HUB_BODY_BYTELEN HUB_WORD * 1 +#define HUB_BODY_BYTEMAX HUB_WORD * 1280 //10KB +#define HUB_TIMEOUT_MS 5000 +#define HUB_HEADER_AUTHSOCK "AUTHSOCK" +#define HUB_HEADER_AUTHFRONT "AUTHFRONT" +#define HUB_HEADER_AUTHFRANK "AUTHFRANK" +#define HUB_HEADER_SENDSOCK "SENDSOCK" +#define HUB_HEADER_RECVSOCK "RECVSOCK" +#define HUB_HEADER_SENDFRONT "SENDFRONT" +#define HUB_HEADER_RECVFRONT "RECVFRONT" +#define HUB_HEADER_SENDFRANK "SENDFRANK" +#define HUB_HEADER_RECVFRANK "RECVFRANK" + +#define TRUE 1 +#define FALSE 0 +#define MAX_BUFF HUB_BODY_BYTEMAX +#define MAX_CONN 80 +#define MAX_ID_LEN 1024 +#define MAX_PW_LEN 4096 +#define PORT_FRONT 3000 +#define PORT_SOCK 3001 + + +#define ISSOCK 1 +#define ISFRONT 2 +#define CHAN_ISSOCK 3 +#define CHAN_ISFRONT 4 + + + +#define MAX_DEVICE_NAME 40 +#define MAX_EVENTS_NO 400 +#define MAX_EVENT_TEXT_SIZE 10 +#define EVENTS_PER_PAGE 20 + +#define MAX_USER_NAME 1024 +#define MAX_USER_PASS 2048 +#define MAX_USER_ACCESS_TOKEN 1024 + +#define MAX_COOKIE_LEN 1024 +#define MAX_COOKIE_KEYLEN 32 + +#define MAX_USERS 10 + +#define MAX_PUBLIC_URI_LEN 512 + +#define MAX_REQUEST_URI_LEN 1024 * 10 +#define MAX_CLIENT_ID_LEN 1024 +#define MAX_CLIENT_SECRET_LEN 1024 +#define MAX_POST_FIELDS_LEN 1024 * 10 + +#define MAX_CODELEN 256 +#define GOAUTH_TOKENLEN 512 + +#define MAX_REST_BUFF 1024 * 10 +#define MAX_WS_BUFF 1024 * 10 + +#define WS_MAX_COMMAND_LEN 32 +#define WS_MAX_COMMAND_DATA_LEN WS_MAX_COMMAND_LEN * 8 +#define WS_MAX_COMMAND_RECV_LEN WS_MAX_COMMAND_LEN * 8 * 8 + +#define WS_COMMAND_REQ_KEY "reqkey" +#define WS_COMMAND_ROUNDTRIP "roundtrip" + +#define DEFAULT_RANDLEN 64 + + + +#ifndef HTTP_URL +#define HTTP_URL "http://0.0.0.0:3000" +#endif + + +#ifndef HTTPS_URL +#define HTTPS_URL "https://0.0.0.0:3443" +#endif + + +#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1}) + +#if __BIG_ENDIAN__ +# define htonll(x) (x) +# define ntohll(x) (x) +#else +# define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) +# define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) +#endif + +#ifndef SERVER_KEY +# define SERVER_KEY "tls/sub_priv.pem" +#endif + +#ifndef SERVER_CERT +# define SERVER_CERT "tls/sub.crt" +#endif + +#ifndef HUB_CA_CERT +# define HUB_CA_CERT "tls/ca.crt" +#endif + +#define DEFAULT_RANDLEN 64 +//#define WAIT 7 + + + + + +struct user { + char name[MAX_USER_NAME]; + char pass[MAX_USER_PASS]; +}; + + +struct CHANNEL_CONTEXT { + int allocated; + int sockfd; + int frontfd; + char id[MAX_ID_LEN]; + char pw[MAX_PW_LEN]; + SSL *ssl; + SSL_CTX *ctx; + int fds[MAX_CONN]; + SSL *ssls[MAX_CONN]; + SSL_CTX *ctxs[MAX_CONN]; +}; + +struct SOCK_CONTEXT { + int allocated; + int sockfd; + SSL *ssl; + SSL_CTX *ctx; + char id[MAX_ID_LEN]; + +}; + + + + +struct HUB_PACKET { + + int ctx_type; + char id[MAX_ID_LEN]; + int fd; + uint8_t header[HUB_HEADER_BYTELEN]; + uint64_t body_len; + uint8_t wbuff[MAX_BUFF]; + uint8_t* rbuff; + + int flag; + +}; + +struct settings { + bool log_enabled; + int log_level; + long brightness; + char *device_name; + }; + + +int make_socket_non_blocking (int sfd); + +SSL_CTX *create_context(); + +void configure_context(SSL_CTX *ctx); + + +int sig_verify(const char* cert_pem, const char* intermediate_pem); + +int extract_common_name(uint8_t* common_name, const char* cert); + +int idpw_verify(char* idpw); + +int update_chanctx_from_userinfo(char* id, char* pw); + +int update_chanctx_from_sockctx(int fd, char* id); + + +int get_chanctx_by_id(char* id); + +int get_chanctx_by_fd(int fd, int type); + +int set_sockctx_by_fd(int fd); + +int get_sockctx_by_fd(int fd); + + + +int calloc_chanctx(); + +int free_chanctx(int idx); + +int calloc_sockctx(); + +int free_sockctx(int idx, int memfree); + + + + +int chanctx_write(int type, char* id, int write_len, uint8_t* wbuff); + +int chanctx_read(int type, char* id, int read_len, uint8_t* rbuff); + +int sockctx_write(int fd, int write_len, uint8_t* wbuff); + +int sockctx_read(int fd, int read_len, uint8_t* rbuff); + + + + +void ctx_write_packet(struct HUB_PACKET* hp); + + +void ctx_read_packet(struct HUB_PACKET* hp); + + + + +extern char CA_CERT[MAX_PW_LEN]; + + +extern int s_sig_num; + + +extern struct settings s_settings; + +extern uint64_t s_boot_timestamp; + +extern char *s_json_header; + +extern struct mg_mgr mgr; + + +extern struct CHANNEL_CONTEXT CHAN_CTX[MAX_CONN]; + +extern struct SOCK_CONTEXT SOCK_CTX[MAX_CONN]; + + + +extern FILE* LOGFP; +extern pthread_mutex_t G_MTX; + +extern int SOCK_FD; +extern int SOCK_SERVLEN; +extern int SOCK_EPLFD; +extern struct epoll_event SOCK_EVENT; +extern struct epoll_event *SOCK_EVENTARRAY; + + +extern int FRONT_FD; +extern int FRONT_SERVLEN; +extern int FRONT_EPLFD; +extern struct epoll_event FRONT_EVENT; +extern struct epoll_event *FRONT_EVENTARRAY; + +extern int MAX_SD; + +extern int OPT; + + + +#endif \ No newline at end of file diff --git a/include/rat-chat/front/core.h b/include/rat-chat/front/core.h new file mode 100644 index 0000000..bdababe --- /dev/null +++ b/include/rat-chat/front/core.h @@ -0,0 +1,36 @@ +#ifndef _FRANK_HUB_FRONT_H_ +#define _FRANK_HUB_FRONT_H_ + +#include "rat-chat/core.h" + + + + + + +void* front_listen_and_serve(void* varg); + + +void sntp_fn(struct mg_connection *c, int ev, void *ev_data); + +void timer_sntp_fn(void *param); + +void route(struct mg_connection *c, int ev, void *ev_data); + + +void front_handler(struct mg_connection *c, struct mg_ws_message *wm); + + +void handle_healtiness_probe(struct mg_connection *c, struct mg_http_message *hm); + + +int front_authenticate(struct mg_connection* c, struct mg_ws_message *wm, int* initial, char* command, char* data); + +void front_communicate(int chan_idx, char* command, char* data); + + + + + + +#endif \ No newline at end of file diff --git a/include/rat-chat/sock/core.h b/include/rat-chat/sock/core.h new file mode 100644 index 0000000..f3da997 --- /dev/null +++ b/include/rat-chat/sock/core.h @@ -0,0 +1,22 @@ +#ifndef _FRANK_HUB_SOCK_H_ +#define _FRANK_HUB_SOCK_H_ + + + +#include "rat-chat/core.h" + + + +void sock_listen_and_serve(void* varg); + + +void sock_handle_conn(); + + +void sock_handle_client(int cfd); + +void sock_authenticate(int cfd); + +void sock_communicate(int chan_idx); + +#endif \ No newline at end of file diff --git a/include/rat-chat/utils.h b/include/rat-chat/utils.h new file mode 100644 index 0000000..f6bd1f6 --- /dev/null +++ b/include/rat-chat/utils.h @@ -0,0 +1,33 @@ +#ifndef _FRANK_HUB_UTILS_H_ +#define _FRANK_HUB_UTILS_H_ + + + +#include "rat-chat/core.h" + + +#define MAX_TIMESTR_LEN 80 +#define MAX_LOG_TXT_LEN 1024 +#define MAX_FMT_ARG_LEN 128 + + +int read_file_to_buffer(uint8_t* buff, int max_buff_len, char* file_path); + +int gen_random_bytestream(uint8_t* bytes, size_t num_bytes); + +int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray); + + + + + + + +void get_current_time_string(char* tstr); + +void sleepms(long ms); + +void fmt_logln(FILE *fp, char* fmt_out, ...); + + +#endif diff --git a/src/core.c b/src/core.c new file mode 100644 index 0000000..406d660 --- /dev/null +++ b/src/core.c @@ -0,0 +1,1095 @@ +#include "rat-chat/core.h" + + +struct CHANNEL_CONTEXT CHAN_CTX[MAX_CONN]; + +struct SOCK_CONTEXT SOCK_CTX[MAX_CONN]; + + + +int make_socket_non_blocking (int sfd){ + int flags, s; + + flags = fcntl (sfd, F_GETFL, 0); + if (flags == -1) + { + perror ("fcntl get"); + return -1; + } + + flags |= O_NONBLOCK; + s = fcntl (sfd, F_SETFL, flags); + if (s == -1) + { + perror ("fcntl set"); + return -2; + } + + return 0; +} + + +SSL_CTX *create_context(){ + + const SSL_METHOD *method; + SSL_CTX *ctx; + + method = TLS_server_method(); + + ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + + return ctx; +} + +void configure_context(SSL_CTX *ctx){ + + if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } + + if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY, SSL_FILETYPE_PEM) <= 0 ) { + ERR_print_errors_fp(stderr); + exit(EXIT_FAILURE); + } +} + +int sig_verify(const char* cert_pem, const char* intermediate_pem){ + + BIO *b = BIO_new(BIO_s_mem()); + BIO_puts(b, intermediate_pem); + X509 * issuer = PEM_read_bio_X509(b, NULL, NULL, NULL); + EVP_PKEY *signing_key=X509_get_pubkey(issuer); + + BIO *c = BIO_new(BIO_s_mem()); + BIO_puts(c, cert_pem); + X509 * x509 = PEM_read_bio_X509(c, NULL, NULL, NULL); + + int result = X509_verify(x509, signing_key); + + EVP_PKEY_free(signing_key); + BIO_free(b); + BIO_free(c); + X509_free(x509); + X509_free(issuer); + + return result; +} + +int extract_common_name(uint8_t* common_name, const char* cert) { + + BIO *b = BIO_new(BIO_s_mem()); + BIO_puts(b, cert); + X509 * x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); + + int ret_cn = -1; + + int common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name(x509), NID_commonName, -1); + if (common_name_loc < 0) { + BIO_free(b); + X509_free(x509); + return ret_cn; + } + + X509_NAME_ENTRY * common_name_entry = X509_NAME_get_entry(X509_get_subject_name(x509), common_name_loc); + if (common_name_entry == NULL) { + BIO_free(b); + X509_free(x509); + return ret_cn; + } + + ASN1_STRING * common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); + if (common_name_asn1 == NULL) { + BIO_free(b); + X509_free(x509); + return ret_cn; + } + + char const * common_name_str = (char const *) ASN1_STRING_get0_data(common_name_asn1); + + if (ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) { + BIO_free(b); + X509_free(x509); + return ret_cn; + } + + strcpy(common_name, common_name_str); + + ret_cn = 1; + + BIO_free(b); + X509_free(x509); + + return ret_cn; +} + + +int idpw_verify(char* idpw){ + + int verify = -1; + + char* token; + + char* delim = ":"; + + uint8_t id[MAX_ID_LEN] = {0}; + uint8_t pw[MAX_PW_LEN] = {0}; + + token = strtok(idpw, delim); + + int idx = 0; + + while( token != NULL ) { + + if(idx > 1) { + break; + } + + if(idx == 0){ + + strncpy(id, token, MAX_ID_LEN); + + } else { + + strncpy(pw, token, MAX_PW_LEN); + + } + + token = strtok(NULL, delim); + + idx += 1; + } + + if(idx != 2){ + return -1; + } + + int chan_idx = get_chanctx_by_id(id); + + if(chan_idx < 0){ + + return -2; + + } + + if(strncmp(CHAN_CTX[chan_idx].pw, pw, MAX_PW_LEN) != 0){ + + return -3; + + } + + int verified_idx = chan_idx; + + + return verified_idx; + +} + +int update_chanctx_from_userinfo(char* id, char* pw){ + + int ret_idx = -1; + + int chan_idx = get_chanctx_by_id(id); + + if(chan_idx < 0){ + + + ret_idx = calloc_chanctx(); + + if(ret_idx < 0){ + + printf("id %s failed to calloc chanctx: max conn\n", id); + + return -2; + + } + + + strcpy(CHAN_CTX[ret_idx].id, id); + strcpy(CHAN_CTX[ret_idx].pw, pw); + + chan_idx = ret_idx; + + printf("id %s added to chanctx from userinfo\n", id); + + + } else { + + + strcpy(CHAN_CTX[chan_idx].pw, pw); + + + printf("id %s modified for existing chanctx from userinfo\n", id); + + + } + + + + ret_idx = chan_idx; + + + return ret_idx; + +} + + +int update_chanctx_from_sockctx(int fd, char* id){ + + + int ret_idx = -1; + + + int sock_idx = get_sockctx_by_fd(fd); + + if(sock_idx < 0){ + + printf("no sock fd associated with: %d\n",fd); + + return -1; + } + + int chan_idx = get_chanctx_by_id(id); + + + if(chan_idx < 0){ + + ret_idx = calloc_chanctx(); + + if(ret_idx < 0){ + + printf("sock fd %d failed to calloc chanctx: max conn\n", fd); + + return -2; + + } + + chan_idx = ret_idx; + + CHAN_CTX[chan_idx].sockfd = SOCK_CTX[sock_idx].sockfd; + CHAN_CTX[chan_idx].ssl = SOCK_CTX[sock_idx].ssl; + CHAN_CTX[chan_idx].ctx = SOCK_CTX[sock_idx].ctx; + + free_sockctx(sock_idx, 0); + + strcpy(CHAN_CTX[chan_idx].id, id); + + printf("id %s added to chanctx %d from sock\n", id, chan_idx); + + } else { + + + CHAN_CTX[chan_idx].sockfd = SOCK_CTX[sock_idx].sockfd; + CHAN_CTX[chan_idx].ssl = SOCK_CTX[sock_idx].ssl; + CHAN_CTX[chan_idx].ctx = SOCK_CTX[sock_idx].ctx; + + free_sockctx(sock_idx, 0); + + printf("id %s modified for existing chanctx from sock\n", id); + + + } + + ret_idx = chan_idx; + + return ret_idx; + +} + + +int get_chanctx_by_id(char* id){ + + + for(int i = 0; i < MAX_CONN; i++){ + + if(strcmp(CHAN_CTX[i].id, id) == 0){ + + return i; + + } + + } + + + return -1; +} + + + +int get_chanctx_by_fd(int fd, int type){ + + + if(type == ISSOCK){ + + for(int i = 0; i < MAX_CONN; i++){ + + if(CHAN_CTX[i].sockfd == fd){ + + return i; + + } + + } + + + } + + + + return -1; +} + + + + + + +int set_sockctx_by_fd(int fd){ + + + int new_idx = calloc_sockctx(); + + if(new_idx < 0){ + + + return -1; + + } + + SOCK_CTX[new_idx].sockfd = fd; + + return new_idx; +} + + + + +int get_sockctx_by_fd(int fd){ + + + for(int i = 0; i < MAX_CONN; i++){ + + + if(SOCK_CTX[i].sockfd == fd){ + + return i; + + } + + + } + + + + return -1; +} + + + + + + +int calloc_chanctx(){ + + for(int i = 0; i < MAX_CONN; i++){ + + + if(CHAN_CTX[i].allocated == 0){ + + CHAN_CTX[i].allocated = 1; + + CHAN_CTX[i].sockfd = 0; + CHAN_CTX[i].frontfd = 0; + + memset(CHAN_CTX[i].id, 0, MAX_ID_LEN * sizeof(char)); + memset(CHAN_CTX[i].pw, 0, MAX_PW_LEN * sizeof(char)); + + CHAN_CTX[i].ssl = NULL; + CHAN_CTX[i].ctx = NULL; + + return i; + + } + + } + + + return -1; +} + + +int free_chanctx(int idx){ + + if(idx >= MAX_CONN){ + + return -10; + } + + if(CHAN_CTX[idx].allocated != 1){ + + return -1; + + } + + if (CHAN_CTX[idx].ssl != NULL){ + + SSL_shutdown(CHAN_CTX[idx].ssl); + SSL_free(CHAN_CTX[idx].ssl); + + } + + if (CHAN_CTX[idx].ctx != NULL){ + + SSL_CTX_free(CHAN_CTX[idx].ctx); + + } + + CHAN_CTX[idx].sockfd = 0; + CHAN_CTX[idx].frontfd = 0; + + + memset(CHAN_CTX[idx].id, 0, MAX_ID_LEN * sizeof(char)); + memset(CHAN_CTX[idx].pw, 0, MAX_PW_LEN * sizeof(char)); + + CHAN_CTX[idx].ssl = NULL; + CHAN_CTX[idx].ctx = NULL; + + CHAN_CTX[idx].allocated = 0; + + return 0; +} + + +int calloc_sockctx(){ + + for(int i = 0; i < MAX_CONN; i++){ + + if(SOCK_CTX[i].allocated == 0){ + + SOCK_CTX[i].ctx = NULL; + SOCK_CTX[i].ssl = NULL; + SOCK_CTX[i].sockfd = 0; + + SOCK_CTX[i].allocated = 1; + + return i; + + } + + + } + + + return -1; +} + + + +int free_sockctx(int idx, int memfree){ + + + if (idx >= MAX_CONN){ + return -10; + } + + if(SOCK_CTX[idx].allocated != 1){ + return -1; + } + + if(memfree == 1){ + + SSL_shutdown(SOCK_CTX[idx].ssl); + SSL_free(SOCK_CTX[idx].ssl); + SSL_CTX_free(SOCK_CTX[idx].ctx); + + } else { + + SOCK_CTX[idx].ssl = NULL; + SOCK_CTX[idx].ctx = NULL; + + } + + SOCK_CTX[idx].sockfd = 0; + SOCK_CTX[idx].allocated = 0; + + + return 0; +} + + +int chanctx_write(int type, char* id, int write_len, uint8_t* wbuff){ + + if(type == ISSOCK){ + + int valwrite = 0; + + int chan_idx = 0; + + chan_idx = get_chanctx_by_id(id); + + if(chan_idx < 0){ + + printf("write: no such id: %s\n", id); + + return -1; + } + + + SSL* sslfd = CHAN_CTX[chan_idx].ssl; + + + valwrite = SSL_write(sslfd, wbuff, write_len); + + + if (valwrite <= 0){ + + printf("write: client gone: %d\n", valwrite); + + return -2; + + } + + return valwrite; + + + } + + + printf("invalid chanctx write type: %d\n", type); + + return -100; + + +} + +int chanctx_read(int type, char* id, int read_len, uint8_t* rbuff){ + + if(type == ISSOCK){ + + int valread = 0; + + int chan_idx = 0; + + int ms_until_deadline = 0; + + chan_idx = get_chanctx_by_id(id); + + if(chan_idx < 0){ + + printf("read: no such id: %s\n", id); + + return -1; + } + + + SSL* sslfd = CHAN_CTX[chan_idx].ssl; + + uint8_t* rbuff_tmp = (uint8_t*)malloc(read_len * sizeof(uint8_t)); + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + int valread_tmp = 0; + + struct timespec rnow; + + clock_gettime(CLOCK_MONOTONIC_RAW, &rnow); + + struct timespec rdeadline; + + while(valread < read_len){ + + clock_gettime(CLOCK_MONOTONIC_RAW, &rdeadline); + + ms_until_deadline = ((rdeadline.tv_sec - rnow.tv_sec) * 1000 + (rdeadline.tv_nsec - rnow.tv_nsec) / 1000000); + + if(ms_until_deadline > HUB_TIMEOUT_MS){ + + printf("time limit exceeded\n"); + + free(rbuff_tmp); + + return -10; + } + + valread_tmp = SSL_read(sslfd, (void*)rbuff_tmp, read_len); + + if(valread_tmp <= 0){ + + if(errno == EAGAIN){ + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + valread_tmp = 0; + + continue; + } + + printf("read: client gone: %d\n", valread); + + free(rbuff_tmp); + + return -2; + } + + for(int i = 0 ; i < valread_tmp; i++){ + + int idx = valread + i; + + rbuff[idx] = rbuff_tmp[i]; + + } + + valread += valread_tmp; + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + valread_tmp = 0; + + } + + + free(rbuff_tmp); + + return valread; + + + } + + + printf("invalid chanctx read type: %d\n", type); + + return -100; + + +} + + +int sockctx_write(int fd, int write_len, uint8_t* wbuff){ + + + int valwrite = 0; + + int sock_idx = 0; + + sock_idx = get_sockctx_by_fd(fd); + + if(sock_idx < 0){ + + printf("write: no such fd: %d\n", fd); + + return -1; + } + + SSL* sslfd = SOCK_CTX[sock_idx].ssl; + + + valwrite = SSL_write(sslfd, (void*)wbuff, write_len); + + if (valwrite <= 0){ + + printf("write: client gone: %d\n", valwrite); + + return -2; + + } + + return valwrite; + + + +} + +int sockctx_read(int fd, int read_len, uint8_t* rbuff){ + + + + int valread = 0; + + int sock_idx = 0; + + int ms_until_deadline = 0; + + sock_idx = get_sockctx_by_fd(fd); + + if(sock_idx < 0){ + + printf("read: no such fd: %d\n", fd); + + return -1; + } + + + SSL* sslfd = SOCK_CTX[sock_idx].ssl; + + uint8_t* rbuff_tmp = (uint8_t*)malloc(read_len * sizeof(uint8_t)); + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + int valread_tmp = 0; + + struct timespec rnow; + + clock_gettime(CLOCK_MONOTONIC_RAW, &rnow); + + struct timespec rdeadline; + + while(valread < read_len){ + + clock_gettime(CLOCK_MONOTONIC_RAW, &rdeadline); + + ms_until_deadline = ((rdeadline.tv_sec - rnow.tv_sec) * 1000 + (rdeadline.tv_nsec - rnow.tv_nsec) / 1000000); + + if(ms_until_deadline > HUB_TIMEOUT_MS){ + + printf("time limit exceeded\n"); + + free(rbuff_tmp); + + return -10; + } + + valread_tmp = SSL_read(sslfd, (void*)rbuff_tmp, read_len); + + if(valread_tmp <= 0){ + + if(errno == EAGAIN){ + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + valread_tmp = 0; + + continue; + } + + printf("read: client gone: %d\n", valread); + + free(rbuff_tmp); + + return -2; + } + + for(int i = 0 ; i < valread_tmp; i++){ + + int idx = valread + i; + + rbuff[idx] = rbuff_tmp[i]; + + } + + valread += valread_tmp; + + memset(rbuff_tmp, 0, read_len * sizeof(uint8_t)); + + valread_tmp = 0; + + } + + free(rbuff_tmp); + + return valread; + + +} + + + + + + + +void ctx_write_packet(struct HUB_PACKET* hp){ + + int valwrite = 0; + + + if(hp->ctx_type == CHAN_ISSOCK){ + + + valwrite = chanctx_write(ISSOCK, hp->id, HUB_HEADER_BYTELEN, hp->header); + + if(valwrite <= 0){ + + printf("packet send header failed\n"); + + hp->flag = valwrite; + + return; + + } + + uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0}; + + uint64_t body_len_new = 0; + + body_len_new = htonll(hp->body_len); + + + memcpy(body_len_byte, &body_len_new, HUB_BODY_BYTELEN); + + + valwrite = chanctx_write(ISSOCK, hp->id, HUB_BODY_BYTELEN, body_len_byte); + + if(valwrite <= 0){ + + printf("packet send body len failed\n"); + + hp->flag = valwrite; + + return; + + } + + valwrite = chanctx_write(ISSOCK, hp->id, hp->body_len, hp->wbuff); + + + if(valwrite <= 0){ + + printf("packet send buff failed\n"); + + hp->flag = valwrite; + + return; + + } + + hp->flag = valwrite; + + return; + + + } + + + if(hp->ctx_type == ISSOCK){ + + valwrite = sockctx_write(hp->fd, HUB_HEADER_BYTELEN, hp->header); + + if(valwrite <= 0){ + + printf("packet send header failed\n"); + + hp->flag = valwrite; + + return; + + } + + uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0}; + + uint64_t body_len_new = 0; + + body_len_new = htonll(hp->body_len); + + memcpy(body_len_byte, &body_len_new, HUB_BODY_BYTELEN); + + valwrite = sockctx_write(hp->fd, HUB_BODY_BYTELEN, body_len_byte); + + if(valwrite <= 0){ + + printf("packet send body len failed\n"); + + hp->flag = valwrite; + + return; + + } + + valwrite = sockctx_write(hp->fd, hp->body_len, hp->wbuff); + + if(valwrite <= 0){ + + printf("packet send buff failed\n"); + + hp->flag = valwrite; + + return; + + } + + hp->flag = valwrite; + + return; + + + } + + + printf("invalid ctx write packet type: %d\n", hp->ctx_type); + + hp->flag = valwrite; + + + return; + +} + + +void ctx_read_packet(struct HUB_PACKET* hp){ + + int valread = 0; + + if(hp->ctx_type == CHAN_ISSOCK){ + + valread = chanctx_read(ISSOCK, hp->id, HUB_HEADER_BYTELEN, hp->header); + + if(valread <= 0){ + + printf("packet recv header failed\n"); + + hp->flag = valread; + + return; + + } + + uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0}; + + uint64_t body_len = 0; + + valread = chanctx_read(ISSOCK, hp->id, HUB_BODY_BYTELEN, body_len_byte); + + + if(valread <= 0){ + + printf("packet recv body len failed\n"); + + hp->flag = valread; + + return; + + } + + memcpy(&body_len, body_len_byte, HUB_BODY_BYTELEN); + + body_len = ntohll(body_len); + + if(body_len > HUB_BODY_BYTEMAX){ + + printf("packet body len too long \n"); + + hp->flag = -10; + + return; + } + + hp->body_len = body_len; + + hp->rbuff = (uint8_t*)malloc(hp->body_len * sizeof(uint8_t)); + + memset(hp->rbuff, 0, hp->body_len * sizeof(uint8_t)); + + valread = chanctx_read(ISSOCK, hp->id, hp->body_len, hp->rbuff); + + if(valread <= 0){ + + printf("packet recv body failed\n"); + + free(hp->rbuff); + + hp->flag = valread; + + return; + + } + + + hp->flag = valread; + + return; + + + } + + + + + + if(hp->ctx_type == ISSOCK){ + + valread = sockctx_read(hp->fd, HUB_HEADER_BYTELEN, hp->header); + + if(valread <= 0){ + + printf("packet recv header failed\n"); + + hp->flag = valread; + + return; + + } + + uint8_t body_len_byte[HUB_BODY_BYTELEN] = {0}; + + uint64_t body_len = 0; + + valread = sockctx_read(hp->fd, HUB_BODY_BYTELEN, body_len_byte); + + if(valread <= 0){ + + printf("packet recv body len failed\n"); + + hp->flag = valread; + + return; + + } + + memcpy(&body_len, body_len_byte, HUB_BODY_BYTELEN); + + body_len = ntohll(body_len); + + if(body_len > HUB_BODY_BYTEMAX){ + + printf("packet body len too long \n"); + + hp->flag = -10; + + return; + } + + hp->body_len = body_len; + + hp->rbuff = (uint8_t*)malloc(hp->body_len * sizeof(uint8_t)); + + memset(hp->rbuff, 0, hp->body_len * sizeof(uint8_t)); + + valread = sockctx_read(hp->fd, hp->body_len, hp->rbuff); + + if(valread <= 0){ + + printf("packet recv body failed\n"); + + free(hp->rbuff); + + hp->flag = valread; + + return; + + } + + hp->flag = valread; + + return; + + + } + + + + + printf("invalid ctx read packet type: %d\n", hp->ctx_type); + + hp->flag = valread; + + return; +} + + + + + diff --git a/src/hubfront/core.c b/src/hubfront/core.c new file mode 100644 index 0000000..c899687 --- /dev/null +++ b/src/hubfront/core.c @@ -0,0 +1,450 @@ +#include "rat-chat/front/core.h" +#include "rat-chat/utils.h" + + +struct settings s_settings = {true, 1, 57, NULL}; + +uint64_t s_boot_timestamp = 0; + +char* s_json_header = + "Content-Type: application/json\r\n" + "Cache-Control: no-cache\r\n"; + +struct mg_mgr mgr; + +int s_sig_num = 0; + + +void sntp_fn(struct mg_connection *c, int ev, void *ev_data) { + uint64_t *expiration_time = (uint64_t *) c->data; + if (ev == MG_EV_OPEN) { + *expiration_time = mg_millis() + 3000; // Store expiration time in 3s + } else if (ev == MG_EV_SNTP_TIME) { + uint64_t t = *(uint64_t *) ev_data; + s_boot_timestamp = t - mg_millis(); + c->is_closing = 1; + } else if (ev == MG_EV_POLL) { + if (mg_millis() > *expiration_time) c->is_closing = 1; + } +} + + +void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time + mg_sntp_connect(param, "udp://time.google.com:123", sntp_fn, NULL); +} + + + + + + +void handle_healtiness_probe(struct mg_connection *c, struct mg_http_message *hm){ + + char* ticket[MAX_USER_PASS] = {0}; + + char rest_buff[MAX_REST_BUFF] = {0}; + + + cJSON* response = cJSON_CreateObject(); + + int datalen = 0; + + + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("success")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("fine")); + + strcpy(rest_buff, cJSON_Print(response)); + + datalen = strlen(rest_buff); + + mg_http_reply(c, 200, "", rest_buff); + + + +} + + + + +void route(struct mg_connection *c, int ev, void *ev_data) { + + if (ev == MG_EV_ACCEPT) { + + if (c->fn_data != NULL) { + struct mg_tls_opts opts = {0}; + opts.cert = mg_unpacked("/certs/server_cert.pem"); + opts.key = mg_unpacked("/certs/server_key.pem"); + mg_tls_init(c, &opts); + } + + } else if (ev == MG_EV_HTTP_MSG) { + + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + + if (mg_match(hm->uri, mg_str("/api/healthz"), NULL)) { + + handle_healtiness_probe(c, hm); + + } + + printf("WS UPGRADE!!!!!\n"); + + mg_ws_upgrade(c, hm, NULL); + + if(DEBUG_THIS == 1){ + + MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len, + hm->method.buf, (int) hm->uri.len, hm->uri.buf, (int) 3, + &c->send.buf[9])); + + } + + } else if (ev == MG_EV_WS_MSG) { + + struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; + + front_handler(c, wm); + + } +} + + + +void* front_listen_and_serve(void* varg){ + + mg_mgr_init(&mgr); + + s_settings.device_name = strdup("rat-chat"); + + mg_http_listen(&mgr, HTTP_URL, route, NULL); + + + mg_timer_add(&mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT, + timer_sntp_fn, &mgr); + + while (s_sig_num == 0) { + mg_mgr_poll(&mgr, 50); + } + + mg_mgr_free(&mgr); + +} + + + + +void front_handler(struct mg_connection *c, struct mg_ws_message *wm){ + + char ws_command[WS_MAX_COMMAND_LEN] = {0}; + + char ws_data[WS_MAX_COMMAND_DATA_LEN] = {0}; + + cJSON* response = cJSON_CreateObject(); + + pthread_mutex_lock(&G_MTX); + + int datalen = 0; + + int initial = 0; + + + int auth_chan_idx = front_authenticate(c, wm, &initial, ws_command, ws_data); + + if (auth_chan_idx < 0){ + + pthread_mutex_unlock(&G_MTX); + + return; + + } + + + if (initial == 1) { + + fmt_logln(LOGFP, "connection authenticated"); + + pthread_mutex_unlock(&G_MTX); + + return; + + } + + front_communicate(auth_chan_idx, ws_command, ws_data); + + pthread_mutex_unlock(&G_MTX); + +} + + + +int front_authenticate(struct mg_connection* c, struct mg_ws_message *wm, int* initial, char* command, char* data){ + + + char ws_buff[MAX_WS_BUFF] = {0}; + + cJSON* response = cJSON_CreateObject(); + + int datalen = 0; + + if(wm->data.len > MAX_WS_BUFF){ + + printf("failed handle ws: data too big\n"); + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -1; + } + + + cJSON* req_obj = cJSON_Parse(wm->data.buf); + + if(req_obj == NULL){ + + printf("failed handle ws: data invalid\n"); + + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -2; + + } + + cJSON* ws_command = cJSON_GetObjectItemCaseSensitive(req_obj, "command"); + + if(ws_command == NULL){ + + printf("failed handle ws: data invalid\n"); + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -3; + + } + + + + printf("command: %s\n", ws_command->valuestring); + + datalen = strlen(ws_command->valuestring); + + if(datalen > WS_MAX_COMMAND_LEN){ + + printf("failed handle ws: command too long\n"); + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -4; + } + + + cJSON* ws_data = cJSON_GetObjectItemCaseSensitive(req_obj, "data"); + + if(ws_data == NULL){ + + printf("failed handle ws: no data field\n"); + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -5; + + } + + int ws_data_len = strlen(ws_data->valuestring); + + if(ws_data_len > WS_MAX_COMMAND_DATA_LEN){ + + printf("failed handle ws: data len too long\n"); + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("null")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -6; + + } + + int frontid = (int)c->id; + + char user_id[MAX_ID_LEN] = {0}; + + + // TODO: + // simple check + + int chan_idx = 0; + + if (chan_idx < 0){ + + fmt_logln(LOGFP,"not registered to chan ctx, auth"); + + int v = idpw_verify(ws_data->valuestring); + + if(v < 0){ + + fmt_logln(LOGFP,"invalid idpw"); + printf("failed handle ws: invalid idpw\n"); + cJSON_AddItemToObject(response, "status", cJSON_CreateString("fail")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("invalid idpw")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + return -10; + + } else { + + fmt_logln(LOGFP, "auth success"); + + + fmt_logln(LOGFP, "initial auth success"); + + printf("handle ws: initial auth success\n"); + cJSON_AddItemToObject(response, "status", cJSON_CreateString("success")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("accepted")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + *initial = 1; + + } + + } + + strcpy(command, ws_command->valuestring); + + strcpy(data, ws_data->valuestring); + + fmt_logln(LOGFP, "auth success"); + + return chan_idx; + + +} + + +void front_communicate(int chan_idx, char* command, char* data){ + + char ws_buff[MAX_WS_BUFF] = {0}; + + cJSON* response = cJSON_CreateObject(); + + int datalen = 0; + + fmt_logln(LOGFP, "incoming front communication to sock"); + + int sockfd = CHAN_CTX[chan_idx].sockfd; + + if(sockfd == 0){ + + + fmt_logln(LOGFP, "no sock exists for communication"); + + + return; + + } + + + fmt_logln(LOGFP, "sock exists"); + + struct HUB_PACKET hp; + + + if (strcmp(command, WS_COMMAND_ROUNDTRIP) == 0) { + + fmt_logln(LOGFP, "roundtrip"); + + + memset(hp.header, 0, HUB_HEADER_BYTELEN); + + memset(hp.wbuff, 0, MAX_BUFF); + + hp.ctx_type = CHAN_ISSOCK; + + strcpy(hp.id, CHAN_CTX[chan_idx].id); + + strcpy(hp.header, HUB_HEADER_SENDSOCK); + + datalen = strlen(data); + + hp.body_len = datalen; + + strncpy(hp.wbuff, data, datalen); + + hp.flag = 0; + + ctx_write_packet(&hp); + + if(hp.flag <= 0){ + + fmt_logln(LOGFP, "failed to send to sock"); + + + + return; + } + + fmt_logln(LOGFP, "send to sock"); + + + } else { + + printf("failed handle ws: no such command\n"); + + + return; + + } + + return; + +} + + diff --git a/src/hubsock/core.c b/src/hubsock/core.c new file mode 100644 index 0000000..58b1323 --- /dev/null +++ b/src/hubsock/core.c @@ -0,0 +1,513 @@ +#include "rat-chat/sock/core.h" +#include "rat-chat/utils.h" + +int SOCK_FD; +int SOCK_SERVLEN; +int SOCK_EPLFD; +struct epoll_event SOCK_EVENT; +struct epoll_event *SOCK_EVENTARRAY; + +char CA_CERT[MAX_PW_LEN] = {0}; + +void sock_listen_and_serve(void* varg){ + + int result = 0; + + SSL_library_init(); + + result = read_file_to_buffer(CA_CERT, MAX_PW_LEN, HUB_CA_CERT); + + if(result < 0){ + + fmt_logln(LOGFP, "failed to read ca cert"); + + return; + + } + + + + struct sockaddr_in SERVADDR; + + for(int i = 0 ; i < MAX_CONN;i ++){ + + CHAN_CTX[i].ssl = NULL; + CHAN_CTX[i].ctx = NULL; + + + } + + + //signal(SIGPIPE, SIG_IGN); + + SOCK_FD = socket(AF_INET, SOCK_STREAM, 0); + + if (SOCK_FD == -1) { + + fmt_logln(LOGFP, "socket creation failed"); + + exit(EXIT_FAILURE); + } + else { + + fmt_logln(LOGFP, "socket successfully created"); + } + /* + if( setsockopt(SOCKFD, SOL_SOCKET, SO_REUSEADDR, (char *)&OPT, + sizeof(OPT)) < 0 ) + { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + */ + + + bzero(&SERVADDR, sizeof(SERVADDR)); + + SERVADDR.sin_family = AF_INET; + SERVADDR.sin_addr.s_addr = htonl(INADDR_ANY); + SERVADDR.sin_port = htons(PORT_SOCK); + + if ((bind(SOCK_FD, (struct sockaddr*)&SERVADDR, sizeof(SERVADDR))) != 0) { + + + fmt_logln(LOGFP, "socket bind failed"); + + exit(EXIT_FAILURE); + } + + if(make_socket_non_blocking(SOCK_FD) < 0){ + + fmt_logln(LOGFP, "non-blocking failed"); + + exit(EXIT_FAILURE); + } + + + if ((listen(SOCK_FD, MAX_CONN)) != 0) { + + fmt_logln(LOGFP, "listen failed"); + + exit(EXIT_FAILURE); + } + else{ + SOCK_SERVLEN = sizeof(SERVADDR); + } + + + SOCK_EPLFD = epoll_create1(0); + + if(SOCK_EPLFD == -1){ + + fmt_logln(LOGFP, "epoll creation failed"); + + exit(EXIT_FAILURE); + } + + SOCK_EVENT.data.fd = SOCK_FD; + SOCK_EVENT.events = EPOLLIN | EPOLLET; + + if (epoll_ctl(SOCK_EPLFD, EPOLL_CTL_ADD, SOCK_FD, &SOCK_EVENT) < 0){ + + fmt_logln(LOGFP,"epoll add failed"); + + exit(EXIT_FAILURE); + } + + SOCK_EVENTARRAY = calloc(MAX_CONN, sizeof(SOCK_EVENT)); + + + while(TRUE){ + + int n, i ; + + n = epoll_wait(SOCK_EPLFD, SOCK_EVENTARRAY, MAX_CONN, -1); + + for (i = 0 ; i < n; i ++){ + + if ( + (SOCK_EVENTARRAY[i].events & EPOLLERR) || + (SOCK_EVENTARRAY[i].events & EPOLLHUP) || + (!(SOCK_EVENTARRAY[i].events & EPOLLIN)) + ){ + + fmt_logln(LOGFP, "epoll wait error"); + + close(SOCK_EVENTARRAY[i].data.fd); + + continue; + + } else if (SOCK_FD == SOCK_EVENTARRAY[i].data.fd){ + + sock_handle_conn(); + + fmt_logln(LOGFP, "new sock conn successfully handled"); + + } else{ + + sock_handle_client(SOCK_EVENTARRAY[i].data.fd); + + fmt_logln(LOGFP, "socket data successfully handled"); + + + } + + } + + + } + + + free(SOCK_EVENTARRAY); + + close(SOCK_FD); + + close(SOCK_EPLFD); + + +} + + + + + +void sock_handle_conn(){ + + + while(TRUE){ + + struct sockaddr in_addr; + socklen_t in_len; + int infd; + SSL *ssl; + SSL_CTX *ctx; + + int ssl_accept_ret; + + in_len = sizeof(in_addr); + + infd = accept(SOCK_FD, &in_addr, &in_len); + + if(infd == -1){ + + if( + (errno == EAGAIN) || + (errno == EWOULDBLOCK) + ){ + + fmt_logln(LOGFP, "all incoming sock connections handled"); + + break; + + } else{ + + fmt_logln(LOGFP, "error handling incoming sock connection"); + + break; + } + } + + ctx = create_context(); + + configure_context(ctx); + + ssl = SSL_new(ctx); + + SSL_set_fd(ssl, infd); + + if((ssl_accept_ret = SSL_accept(ssl)) < 1){ + + int sslerr = SSL_get_error(ssl, 0); + + fmt_logln(LOGFP, "error handling tls handshake"); + + if (ssl_accept_ret <=0 && (sslerr == SSL_ERROR_WANT_READ)) { + + perror ("Need to wait until socket is readable."); + + fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is readable"); + + } else if (ssl_accept_ret <=0 && (sslerr == SSL_ERROR_WANT_WRITE)) { + + perror ("Need to wait until socket is writable."); + + fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is writable"); + + + } else { + perror ("Need to wait until socket is ready."); + + fmt_logln(LOGFP, "ssl: %s", "Need to wait until socket is ready"); + + } + + shutdown (infd, 2); + SSL_free (ssl); + SSL_CTX_free(ctx); + + continue; + + } + + + if(make_socket_non_blocking(infd) < 0){ + + fmt_logln(LOGFP, "failed new conn non block"); + + exit(EXIT_FAILURE); + } + + int sock_idx = set_sockctx_by_fd(infd); + + + + if(sock_idx < 0){ + + fmt_logln(LOGFP, "failed new conn sockctx"); + + exit(EXIT_FAILURE); + + } + + SOCK_CTX[sock_idx].ctx = ctx; + SOCK_CTX[sock_idx].ssl = ssl; + + + SOCK_EVENT.data.fd = infd; + SOCK_EVENT.events = EPOLLIN | EPOLLET; + + if (epoll_ctl(SOCK_EPLFD, EPOLL_CTL_ADD, infd, &SOCK_EVENT) < 0){ + + fmt_logln(LOGFP,"handle epoll add failed"); + + + exit(EXIT_FAILURE); + + } else { + + fmt_logln(LOGFP,"handle epoll add success"); + + } + + + + } + + + +} + + + +void sock_handle_client(int cfd){ + + + pthread_mutex_lock(&G_MTX); + + int chan_idx = get_chanctx_by_fd(cfd, ISSOCK); + + + if(chan_idx < 0){ + + sock_authenticate(cfd); + + pthread_mutex_unlock(&G_MTX); + + return; + } + + sock_communicate(chan_idx); + + pthread_mutex_unlock(&G_MTX); + + return; + +} + + + +void sock_authenticate(int cfd){ + + int valread; + int valwrite; + + struct HUB_PACKET hp; + + + uint8_t id[MAX_ID_LEN] = {0}; + + int sock_idx = get_sockctx_by_fd(cfd); + + fmt_logln(LOGFP,"not registered to chan ctx, auth"); + + if(sock_idx < 0){ + + fmt_logln(LOGFP,"failed to get sock idx"); + + return; + } + + + hp.ctx_type = ISSOCK; + hp.fd = SOCK_CTX[sock_idx].sockfd; + + ctx_read_packet(&hp); + + if(hp.flag <= 0){ + + + fmt_logln(LOGFP,"failed to read sock"); + + free_sockctx(sock_idx, 1); + + return; + + } + + + + int verified = sig_verify(hp.rbuff, CA_CERT); + + if(verified < 1){ + + fmt_logln(LOGFP,"invalid signature"); + + free_sockctx(sock_idx, 1); + + free(hp.rbuff); + + return; + + } + + + + int ret_cn = extract_common_name(id, hp.rbuff); + + if(ret_cn != 1){ + + fmt_logln(LOGFP,"invalid id"); + + free_sockctx(sock_idx, 1); + + free(hp.rbuff); + + return; + + + } + + fmt_logln(LOGFP, "id: %s", id); + + free(hp.rbuff); + + int chan_idx = update_chanctx_from_sockctx(cfd, id); + + if (chan_idx < 0){ + + fmt_logln(LOGFP, "failed to update chanctx"); + + free_sockctx(sock_idx, 1); + + return; + + } + + + uint64_t body_len = strlen("SUCCESS") + 1; + + memset(hp.header, 0, HUB_HEADER_BYTELEN); + + memset(hp.wbuff, 0, MAX_BUFF); + + hp.ctx_type = CHAN_ISSOCK; + + strcpy(hp.header, HUB_HEADER_AUTHSOCK); + + hp.body_len = body_len; + + strcat(hp.wbuff,"SUCCESS"); + + strcpy(hp.id, id); + + fmt_logln(LOGFP, "writing auth result.."); + + ctx_write_packet(&hp); + + if(hp.flag <= 0){ + + fmt_logln(LOGFP, "failed to send"); + + return; + + } + + fmt_logln(LOGFP, "sent"); + + return; + + +} + + + +void sock_communicate(int chan_idx){ + + fmt_logln(LOGFP, "incoming sock communication to front"); + + int frontfd = CHAN_CTX[chan_idx].frontfd; + + if(frontfd == 0){ + + fmt_logln(LOGFP, "no front exists for communication"); + + return; + + } + + fmt_logln(LOGFP, "front exists"); + + struct HUB_PACKET hp; + + hp.ctx_type = CHAN_ISSOCK; + + strcpy(hp.id, CHAN_CTX[chan_idx].id); + + ctx_read_packet(&hp); + + if(hp.flag <= 0){ + + fmt_logln(LOGFP, "failed to communicate sock read"); + + return; + + } + + memset(hp.header, 0, HUB_HEADER_BYTELEN); + + memset(hp.wbuff, 0, MAX_BUFF); + + hp.ctx_type = CHAN_ISFRONT; + + strcpy(hp.header, HUB_HEADER_RECVFRONT); + + strncpy(hp.wbuff, hp.rbuff, hp.body_len); + + hp.flag = 0; + + free(hp.rbuff); + + ctx_write_packet(&hp); + + if(hp.flag <= 0){ + + fmt_logln(LOGFP, "failed to send to front"); + + return; + } + + fmt_logln(LOGFP, "send to front"); + + return; +} \ No newline at end of file diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..7670b5e --- /dev/null +++ b/src/utils.c @@ -0,0 +1,250 @@ +#include "rat-chat/utils.h" + + +int read_file_to_buffer(uint8_t* buff, int max_buff_len, char* file_path){ + + + int valread = 0 ; + + int c; + + FILE* fp; + + fp = fopen(file_path, "r"); + + while(1) { + + c = fgetc(fp); + if( feof(fp) ) { + break; + } + + + buff[valread] = c; + + valread += 1; + + if(valread > max_buff_len){ + + return -10; + } + + } + + return valread; +} + +int gen_random_bytestream(uint8_t* bytes, size_t num_bytes){ + + + if(num_bytes > MAX_PW_LEN){ + + return -1; + + } + + + size_t i; + + for (i = 0; i < num_bytes; i++){ + + bytes[i] = rand(); + + } + + return 0; + +} + +int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray){ + + int hexlen = 2; + + int outstrlen = hexlen * arrlen + 1; + + if (outstrlen > MAX_PW_LEN){ + + return -1; + } + + memset(hexarray, 0, outstrlen * sizeof(char)); + + unsigned char* ptr = hexarray; + + for(int i = 0 ; i < arrlen; i++){ + + sprintf(ptr + 2 * i, "%02X", bytearray[i]); + } + + return 0; + +} + + + +void get_current_time_string(char* tstr){ + + + struct tm *info; + + int millisec; + char msec_str[5] = {0}; + + struct timeval tv; + + + gettimeofday(&tv, NULL); + + + millisec = tv.tv_usec / 1000; + + if (millisec >= 1000){ + + millisec -= 1000; + tv.tv_sec += 1; + + } + + + + + info = localtime(&tv.tv_sec); + + strftime(tstr, MAX_TIMESTR_LEN, "%Y-%m-%d %H:%M:%S", info); + + sprintf(msec_str, ".%03d", millisec); + + strcat(tstr, msec_str); + + +} + +void sleepms(long ms){ + + + struct timespec ts; + int res; + + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000; + + nanosleep(&ts, &ts); + + + +} + +void fmt_logln(FILE *fp, char* fmt_out, ...){ + + va_list valist; + + char log_str[MAX_LOG_TXT_LEN] = {0}; + + char log_fmt_str[MAX_LOG_TXT_LEN] = {0}; + + char fmt_arg[MAX_FMT_ARG_LEN] = {0}; + + char time_str[MAX_TIMESTR_LEN] = {0}; + + + + int arg_len = 0; + + int str_len = strlen(fmt_out); + + if(str_len < 1){ + return; + } + + for(int i = 0; i < str_len; i++){ + + if(fmt_out[i] == '%' && i != 0 && fmt_out[i - 1] != '\\'){ + + arg_len += 1; + + } + + } + + get_current_time_string(time_str); + + if(arg_len == 0){ + + sprintf(log_str, "[ %s ] %s\n", time_str, fmt_out); + + } else { + + char fmt_flag[3] = {0}; + + va_start(valist, arg_len); + + int i = 0; + + int fmt_i = 0; + + for(;;){ + + if(fmt_out[i] == '%' && i != 0 && i != (str_len - 1) && fmt_out[i - 1] != '\\'){ + + fmt_flag[0] = fmt_out[i]; + + i += 1; + + fmt_flag[1] = fmt_out[i]; + + fmt_flag[2] = 0; + + memset(fmt_arg, 0, MAX_FMT_ARG_LEN); + + if(fmt_flag[1] == 'd'){ + + int a = va_arg(valist, int); + + sprintf(fmt_arg, fmt_flag, a); + + + } else if (fmt_flag[1] == 's') { + + char* a = va_arg(valist, char*); + + sprintf(fmt_arg, fmt_flag, a); + + } + + strcat(log_fmt_str, fmt_arg); + + int added = strlen(fmt_arg); + + i += 1; + fmt_i += added; + + + } else { + + log_fmt_str[fmt_i] = fmt_out[i]; + + i += 1; + fmt_i += 1; + + } + + + if(i >= str_len){ + break; + } + + } + + va_end(valist); + + sprintf(log_str, "[ %s ] %s\n", time_str, log_fmt_str); + } + + + fputs(log_str, fp); + + fflush(fp); + + + +} \ No newline at end of file diff --git a/tls/ca.crt b/tls/ca.crt new file mode 100644 index 0000000..f22de82 --- /dev/null +++ b/tls/ca.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFTCCAv2gAwIBAgIUKEjIY8AOTELEiqp/Rx/zYdclnVcwDQYJKoZIhvcNAQEL +BQAwGjEYMBYGA1UEAwwPY2FAZmVlYmRhZWQueHl6MB4XDTI0MDUwNDAyMDUxOVoX +DTM0MDUwMjAyMDUxOVowGjEYMBYGA1UEAwwPY2FAZmVlYmRhZWQueHl6MIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuiTwW9Fkha7BNq/tF+ZRePIvlDBw +h/div9RmCbneMdd1qot5iuS2BXpuzVLlSwKEKoUntRSfIjRj2Q3NDJ95XGocsCuT +Prj8Bt1t+Kwr5NwyOn1ea6mXMJnMqRlnQznDDWVj+/mVXdJzBc175viToCWk8F/b +RyJhYQVUL8xXu+CiNQCkRuzdo6UBfTQBlpdoN0x44w5Td083En548qn4jAOhO+mw +mrO8+WsAyMPNFBLNEXBKF1PN3nC7ryySRLlE/rxnDGxSShjDI0ItgNTFr6rhUenK +d6n/czM72WdUkHPLPIEO6DN+EDfCPMl9gz/gy3Zrfxg/nuEwrV7GtT69+5diesSt +AJ2BRUScF1RKVevuzOGB3w2SSiZO4CbxYvvwYQA0MLE9Uhvexkq1xGkkgEqOaFHd +w3EoTT+Q7JXgA70vGXhp0tOMtkYSGN84gBvXZbB9g7gpZbaZe7L0Mn3tBqqWjEcF +OdrquXyfP2/9dbCAnL6AVitGZ74UKbV4U1TxW//+ysDt6h3ns3M+y5krFdVe/FkY +XIyzTJyyqZqtrqX8xG2F72KFCQ0lBTtQm664rufa7UoVE32Lt6b2GasHn8dJVDbj +i06p07BHkiLNf3YbGPSebh3Sm258LaY+eTK/R/y/hRjxyDAka9ng8eps1m3vdewd +4SCmLD1ou3b6rxsCAwEAAaNTMFEwHQYDVR0OBBYEFBgBUQHuYfawyeL0Z7ymU4QE +jcylMB8GA1UdIwQYMBaAFBgBUQHuYfawyeL0Z7ymU4QEjcylMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQELBQADggIBACf3RPLAjt+DAijU5YG41E0KZ5lQj3PT +wla+5PB/8avVjgKvP1mkcGhYEq75DRT1T9MdnPRKUCqZCcRUb2nPQCaq/jNSOdbs +OnlM9qJTZJezwOthUMCNwBMLJJbvTBBrLyaRXaCHN1wcfavIyGMCrqVKW0FfwhaF +UgwAhG4maTw283lq+/j/9xoPuP7XHkbkRDW3TINS0dEQM1RNNKPVdyMOErKLNBaT +9DRFWKjRXk2ZtBJ1XxAyT9LipfUVYgjETX/iVV3kknsngM2rtMpjb6W+9f7pfOuh +gUacxpLflBVkzXYFgsLm6p+wg0l9V3zuaEZELIo2KgcT1jwpBgXvjtye5urKElkh +JHr07raS8JFrF+L8lcjaXhb28lLDp4fRT8GHEl1/naASVvtZxlEEXnnrkJ6A0jD0 +Vt8balZMYZDoq+A4iYPk6LlHgsYOOnH87L7dhqED+xAZm6fzDZyilUioTVtmIOsC +5/ybtUdYrK1n9PqfhA/awYYW2vY7M3HFkEjy+gf3VOcdFzpssSUJmyt359B/VRDR +V5ISq4JA5CyoO/2yKbLEiKW7kY8DiiQjKQ+27zB+KUB0yVSO+xb1dm93zOE29yql +3cQgBN2CW13Xe/rMNdu53ToE0FIwheRBXtiPsh+bw7MDUStbgIOz/mAszWcbLcai +ZVo3eVTwCWoN +-----END CERTIFICATE----- diff --git a/tls/list.txt b/tls/list.txt new file mode 100644 index 0000000..a2910b9 --- /dev/null +++ b/tls/list.txt @@ -0,0 +1,4 @@ +sub_priv.pem +sub_pub.pem +sub.csr +sub.crt \ No newline at end of file diff --git a/tls/sub.crt b/tls/sub.crt new file mode 100644 index 0000000..79d54a5 --- /dev/null +++ b/tls/sub.crt @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEwzCCAqsCFGJACNTxHt8lNKG5UoBZHFyKF+frMA0GCSqGSIb3DQEBCwUAMBox +GDAWBgNVBAMMD2NhQGZlZWJkYWVkLnh5ejAeFw0yNDA1MDQwMjA1MjFaFw0yNTA1 +MDQwMjA1MjFaMCIxIDAeBgNVBAMMF3NlYW50eXdvcmtAZmVlYmRhZWQueHl6MIIC +IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxP8l01USO8HYM9S/5q/9GnJu +Xdx5dTOG4YpFaQdQ+hUfGaBc76D/FnRQE2XgL6r1DZ4tEwy3BZ1UXr3AiOzKQzse +l8/E1ChgsF8RPXNNIFjkR9EHSMBjC5Wq6T0ATWG8CR/0I4VD7S3Tdd9caT41RbbJ +WE3lY9S92hn47X+b6ae48UdMn+d2ZNpCQ22nk7chee/UJhQLTQv69IkvonYPJPP8 +PStkzq72xV8Mj28zU0D+Eua2BvDpA76DO08xPB9BprGgF2aqZ3yI63tFWy+kgEXF +LPLsU6T+wA05dztewBuCQCdfs1NJWwF3JI2HUfDhRc05IO1aV1I6Dq1W9ZH5EyBz +tGXOD/+ec46AR8h1gpEgir894MdxdP562y1zShRs8nm0DKjkeewgYQ6+2AaTq+jC +H020y9nRFNIO4sXntl4xYsRVR9G90PosVbOv95NkgWpGWTW/6BtxjVQ/5iI1w9ae +DmPD7NqD6cIC53TEPllWr1rv1xwO91ZIzoM/5PgLGBIhwWWXK6BDwVU4YOled0Yd +jr6me7+95+QrEFK7M+Ar4sBnxSBn2BEc6rGOaeG8TbKBMkt4JQJuwbsIQcAWfQmD +AGDoCzxT4+Y53Z+Rlc4SUurbPeoFE+1PsmnVyHQSyes29DzPQKUSUO67I36YP7fO +AWNv/NQew7UzDFJV8kMCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAThTtYGycDU8a +y50NIuz1laYfHLVRT95LSkzq3qZLiQk4ZEP0nVEEWMueY17ObaQ6WC9EY9r+JqAG +Ng0eUcchVtQoCveeUjKXVQZNTc1pgW5UVHlfzbxgSlDGWB3wwssywMDeubnToalz +1ksnBPLX7KWnmZWFCjU7jIBUdy0qYdVRH6IaWuAQZJ41FfszWfRnFAuaQFxnZtkt +fjanuGYKQophT3tu8yCYFr6YqT44FrQ0DIJHRs5F9jUsg7aQTnWlmhmmDMxoPr0T +ycObH4ZwHbexqzwJGH/ZoX0Sf/bFmFtf/K3xytt921cxMjF8MpjVIx6NrgSy8Ngr +gRW+XiNW0aRlimYKu0ES9dhKRywXHH7R22sivRWdDWv1t1lo+Lr5EMTM68sO09+s +KO6z0OKgyfBT7VHzPAsCo2tPFORBlEkh/siKEWyiMgWYN/3KIQT1HDjObmOyCuxE +Yz7QuRKrHbkQPKu9zTVa6/stX8X82nSet5JPF/LIO5h+R971gkxIjpKHlBWJlvqw +22UIkJ1s/05G1YqfRef6ADTWEN8xBWyiIhuIYcly/HI5DjMZ/J3VzSbk/JajSGIc +lRqrn/I0Lfefb1gKZ9DNydzSIBwtv4jikYaLhov0jugSze8bSKf+ktR30JCXXtv2 +IPXwvSGLSRtzfqlRRu9Lx4RMvzSNY7I= +-----END CERTIFICATE----- diff --git a/tls/sub.csr b/tls/sub.csr new file mode 100644 index 0000000..1cf4784 --- /dev/null +++ b/tls/sub.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEZzCCAk8CAQAwIjEgMB4GA1UEAwwXc2VhbnR5d29ya0BmZWViZGFlZC54eXow +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDE/yXTVRI7wdgz1L/mr/0a +cm5d3Hl1M4bhikVpB1D6FR8ZoFzvoP8WdFATZeAvqvUNni0TDLcFnVRevcCI7MpD +Ox6Xz8TUKGCwXxE9c00gWORH0QdIwGMLlarpPQBNYbwJH/QjhUPtLdN131xpPjVF +tslYTeVj1L3aGfjtf5vpp7jxR0yf53Zk2kJDbaeTtyF579QmFAtNC/r0iS+idg8k +8/w9K2TOrvbFXwyPbzNTQP4S5rYG8OkDvoM7TzE8H0GmsaAXZqpnfIjre0VbL6SA +RcUs8uxTpP7ADTl3O17AG4JAJ1+zU0lbAXckjYdR8OFFzTkg7VpXUjoOrVb1kfkT +IHO0Zc4P/55zjoBHyHWCkSCKvz3gx3F0/nrbLXNKFGzyebQMqOR57CBhDr7YBpOr +6MIfTbTL2dEU0g7ixee2XjFixFVH0b3Q+ixVs6/3k2SBakZZNb/oG3GNVD/mIjXD +1p4OY8Ps2oPpwgLndMQ+WVavWu/XHA73VkjOgz/k+AsYEiHBZZcroEPBVThg6V53 +Rh2OvqZ7v73n5CsQUrsz4CviwGfFIGfYERzqsY5p4bxNsoEyS3glAm7BuwhBwBZ9 +CYMAYOgLPFPj5jndn5GVzhJS6ts96gUT7U+yadXIdBLJ6zb0PM9ApRJQ7rsjfpg/ +t84BY2/81B7DtTMMUlXyQwIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAJftxdPt +5rCVHS3SWg7YzlQeHL1pIUtEM+YmK/BMr/3SI3l54CvrVl4yquADa3FUxhwEE9jq +CguHqj0FxpPX9vyN9YfSUmWbn5zzYyifgkf4VVepDOvUhwl5NmP2HwpjgsV8dIaH +e84a/V7AWdn3OE6+fZOhDtCeP0sJKQ8NyGGvs/UsAvRE8+JPXnf06P7/aGK5L4Cj +wZoK6RyaoP0dR1rMZDWKQzd2ObhvffzfSEGdnZUNNSsIiTDktvZx46Yf9ZOxj+UB +KKbajqB2VvOn10egBQ/VrJ2BimCp4GcPVICaMR65QDVcRPL7xErXMRQ2vWCb8Qep +SB1Hj8Jji/OcDJO14goMuomnkawpHLiErtlekuKMBD3ILtjbfF73I8YaagmA0IGq +81gk7W0JG/3VhchHhy3gRVxN3WgEnFFN8pCD5SOr0/diGmpCYoiUzfoC79bH0bIP +CK2E0af4N4LZ+EXTKyGvCIwjNcMM7wiaJxOtwD5+83KHtkP4kfHklW4AFF9YcCDJ +oG5V2SG+V7rtERnkTcCbm1NYh6oyB9VGa5bu9ln7MBxmkNjdECr4mklM3tBamvXw +HZyYGkWzpSo+bA5CbxtEdga9pn4zt/R3sUf04JYIjYEF+XP0mAI4Q6kAHCS/T/hJ +01UfO+W/ws6BnT1MVBiiglzpkN4S3Dn4jC9Z +-----END CERTIFICATE REQUEST----- diff --git a/vendor/.gitignore b/vendor/.gitignore new file mode 100644 index 0000000..9b4f2c1 --- /dev/null +++ b/vendor/.gitignore @@ -0,0 +1,2 @@ +mongoose +cJSON \ No newline at end of file diff --git a/vendor/README.md b/vendor/README.md new file mode 100644 index 0000000..e69de29 -- 2.43.0