From bd7b6eda94889615fa9e4d032528d996d2eb43e6 Mon Sep 17 00:00:00 2001 From: seantywork Date: Tue, 25 Feb 2025 14:33:03 +0000 Subject: [PATCH] add gencert --- hack/tls.sh | 2 +- include/socialize/core.h | 4 + include/socialize/front/front.h | 2 +- public/index.html | 35 ++--- public/js/common.js | 0 public/{ => public}/css/common.css | 0 public/public/js/common.js | 186 ++++++++++++++++++++++++ src/ctl.c | 6 +- src/front/front.c | 221 +++++++++++++++++++++++++++-- src/utils.c | 6 +- 10 files changed, 427 insertions(+), 35 deletions(-) delete mode 100644 public/js/common.js rename public/{ => public}/css/common.css (100%) create mode 100644 public/public/js/common.js diff --git a/hack/tls.sh b/hack/tls.sh index 7f1f46e..81dbea2 100755 --- a/hack/tls.sh +++ b/hack/tls.sh @@ -7,7 +7,7 @@ openssl genrsa -out ca_priv.pem 4096 openssl rsa -in ca_priv.pem -outform PEM -pubout -out ca_pub.pem -openssl req -x509 -new -key ca_priv.pem -days 365 -out ca.crt.pem -subj "/CN=testca" +openssl req -x509 -new -key ca_priv.pem -days 365 -out ca.crt.pem -subj "/CN=socializeca" echo "gen server..." diff --git a/include/socialize/core.h b/include/socialize/core.h index 83d1e9e..a26bf66 100644 --- a/include/socialize/core.h +++ b/include/socialize/core.h @@ -112,6 +112,8 @@ #define WS_COMMAND_REQ_KEY "reqkey" #define WS_COMMAND_ROUNDTRIP "roundtrip" +#define WS_COMMAND_GENCERT "gencert" + #define DEFAULT_RANDLEN 64 @@ -145,6 +147,8 @@ # define SERVER_CERT "tls/server.crt.pem" #endif +#define HUB_CA_NAME "socializeca" + #ifndef HUB_CA_CERT # define HUB_CA_CERT "tls/ca.crt.pem" #endif diff --git a/include/socialize/front/front.h b/include/socialize/front/front.h index 9b576f2..8583425 100644 --- a/include/socialize/front/front.h +++ b/include/socialize/front/front.h @@ -30,7 +30,7 @@ int front_access(struct mg_connection* c, struct mg_ws_message *wm, char* comman void front_communicate(struct mg_connection* c, struct mg_ws_message *wm, char* command, char* data); - +int gencert(char* newcert, char* cname); diff --git a/public/index.html b/public/index.html index a33dedb..f8a5f74 100644 --- a/public/index.html +++ b/public/index.html @@ -23,27 +23,28 @@
- -
-
- - +
+
+
+ + +
-
- -
-
- - + +
+
+ + +
+
+ +
+
+ +
-
-
- -
diff --git a/public/js/common.js b/public/js/common.js deleted file mode 100644 index e69de29..0000000 diff --git a/public/css/common.css b/public/public/css/common.css similarity index 100% rename from public/css/common.css rename to public/public/css/common.css diff --git a/public/public/js/common.js b/public/public/js/common.js new file mode 100644 index 0000000..35b3eb1 --- /dev/null +++ b/public/public/js/common.js @@ -0,0 +1,186 @@ + +ws = {} + +MESSAGE_FORMAT = { + + command: "", + data: "" + +} + +resumeToken = "" +resumeCount = 0 +resumeThreshold = 10 + +step = 0 + + +let newUI = ` + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + + +` + +function signin(){ + + + let email = document.getElementById("email").value + + let password = document.getElementById("password").value + + if(email == ""){ + + alert("email is empty") + + return + } + + if(password == ""){ + + alert("password is empty") + + return + } + + + ws = new WebSocket("/front") + + + let cred = email + ":" + password + + ws.onopen = function(evt){ + + ws.send(JSON.stringify({command: "auth", data: cred})) + + } + + ws.onclose = function(evt) { + alert("connection to server has closed") + } + + ws.onmessage = function(evt) { + + let msg = JSON.parse(evt.data) + + if (!msg) { + + alert("failed to parse msg") + + return + } + + + let data = msg.data + + if(step == 0){ + + if(msg.status != "success") { + + alert("failed to auth") + + return + } + + resumeToken = data + + + sendMessage("auth", data) + + step = 1 + + return + } + + + if(step == 1){ + + if(msg.status != "success") { + + if(resumeToken != ""){ + + if(resumeCount > resumeThreshold){ + + alert("failed to connect") + + return + } + + sendMessage("auth", resumeToken) + + resumeCount += 1 + return + } + + alert("failed to connect") + + return + } + + let adminpage = document.getElementById("socialize-admin") + + adminpage.innerHTML = newUI + + step = 2 + + return + } + + if(msg.status == "success") { + + alert("got data: \n" + msg.data) + + return + + } else { + + alert("failed: " + msg.status) + } + + return + + } + + ws.onerror = function(evt) { + console.log("error: " + evt.data) + } + +} + +function sendFromUI(){ + + let cmd = document.getElementById("command").value + + let msg = document.getElementById("data").value + + sendMessage(cmd, msg) + +} + +function sendMessage(cmd, msg){ + + let req = JSON.parse(JSON.stringify(MESSAGE_FORMAT)) + + req.command = cmd + req.data = msg + + ws.send(JSON.stringify(req)) + +} + diff --git a/src/ctl.c b/src/ctl.c index 678e362..817c6e4 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -205,15 +205,13 @@ int idpw_verify(char* idpw, char *newid, uint8_t* newtoken){ } - memset(idpw, 0, idpwlen); - int idlen = strlen(id); strncpy(newid, id, idlen); - int arrlen = gen_random_bytestream(newtoken, 64); + gen_random_bytestream(newtoken, 64); - bin2hex(newtoken, arrlen, newtoken); + bin2hex(newtoken, 64, newtoken); return 0; diff --git a/src/front/front.c b/src/front/front.c index a3ac3a2..51cf7cd 100644 --- a/src/front/front.c +++ b/src/front/front.c @@ -18,6 +18,79 @@ struct mg_mgr mgr; int s_sig_num = 0; +static BIO* _keygen(int bits){ + + RSA *r; + BIGNUM *bne; + BIO *bp_public; + BIO *bp_private; + + + EVP_PKEY *pkey; + + + int ret = 0; + + unsigned long e = RSA_F4; + + + bne = BN_new(); + ret = BN_set_word(bne,e); + if(ret != 1){ + + goto FREE_KEYGEN; + } + + r = RSA_new(); + ret = RSA_generate_key_ex(r, bits, bne, NULL); + if(ret != 1){ + goto FREE_KEYGEN; + } + + bp_private = BIO_new(BIO_s_mem()); + + ret = PEM_write_bio_RSAPrivateKey(bp_private, r, NULL, NULL, 0, NULL, NULL); + if(ret != 1){ + goto FREE_KEYGEN; + } + + bp_public = BIO_new(BIO_s_mem()); + ret = PEM_write_bio_RSAPublicKey(bp_public, r); + if(ret != 1){ + bp_public = NULL; + goto FREE_KEYGEN; + } + + goto EXIT_KEYGEN; + +FREE_KEYGEN: + + if(bp_public != NULL){ + + BIO_free_all(bp_public); + } + +EXIT_KEYGEN: + + if(bp_private != NULL){ + + BIO_free_all(bp_private); + } + + if(r != NULL){ + + RSA_free(r); + } + + if(bne != NULL){ + + BN_free(bne); + } + + return bp_public; +} + + 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) { @@ -152,10 +225,14 @@ void route(struct mg_connection *c, int ev, void *ev_data) { } else if (mg_match(hm->uri, mg_str("/front"), NULL)) { - printf("WS UPGRADE!!!!!\n"); + printf("ws upgrade init\n"); mg_ws_upgrade(c, hm, NULL); + printf("ws upgraded\n"); + + return; + } else { struct mg_http_serve_opts opts = {.root_dir = FRONT_WEB_ROOT}; @@ -175,15 +252,11 @@ void route(struct mg_connection *c, int ev, void *ev_data) { } else if (ev == MG_EV_WS_MSG) { - struct mg_http_message *hm = (struct mg_http_message *) ev_data; - struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; - - if (mg_match(hm->uri, mg_str("/front"), NULL)) { - front_handler(c, wm); - } + front_handler(c, wm); + } } @@ -257,6 +330,8 @@ int front_access(struct mg_connection* c, struct mg_ws_message *wm, char* comman int datalen = 0; + printf("access handler\n"); + if(wm->data.len > MAX_WS_BUFF){ printf("failed handle ws: data too big\n"); @@ -407,6 +482,9 @@ int front_access(struct mg_connection* c, struct mg_ws_message *wm, char* comman fmt_logln(LOGFP, "initial auth success"); printf("handle ws: initial auth success\n"); + + strcpy(USER.token, token); + cJSON_AddItemToObject(response, "status", cJSON_CreateString("success")); cJSON_AddItemToObject(response, "data", cJSON_CreateString((char*)token)); @@ -456,17 +534,58 @@ void front_communicate(struct mg_connection* c, struct mg_ws_message *wm, char* int datalen = 0; + int result = 0; + fmt_logln(LOGFP, "incoming front communication"); - if (strcmp(command, WS_COMMAND_ROUNDTRIP) == 0) { + if (strcmp(command, WS_COMMAND_GENCERT) == 0) { + + fmt_logln(LOGFP, "gencert"); - fmt_logln(LOGFP, "roundtrip"); + char newcert[MAX_BUFF] = {0}; + + result = gencert(newcert, data); + + if(result < 0){ + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("failed")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("gencert failed")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + + } else { + + cJSON_AddItemToObject(response, "status", cJSON_CreateString("success")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString(newcert)); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + + + } } else { printf("failed handle ws: no such command\n"); + cJSON_AddItemToObject(response, "status", cJSON_CreateString("failed")); + cJSON_AddItemToObject(response, "data", cJSON_CreateString("no such command")); + + strcpy(ws_buff, cJSON_Print(response)); + + datalen = strlen(ws_buff); + + mg_ws_send(c, ws_buff, datalen, WEBSOCKET_OP_TEXT); + } return; @@ -474,3 +593,87 @@ void front_communicate(struct mg_connection* c, struct mg_ws_message *wm, char* } +int gencert(char* newcert, char* cname){ + + + time_t exp_ca; + time(&exp_ca); + exp_ca += 315360000; + + time_t exp_s; + time(&exp_s); + exp_s += 31536000; + + X509* x509_s = X509_new(); + + EVP_PKEY* pub_key_s = EVP_PKEY_new(); + + X509_NAME* ca_name = X509_NAME_new(); + X509_NAME* s_name = X509_NAME_new(); + X509_NAME_add_entry_by_txt(ca_name, "CN" , MBSTRING_ASC, HUB_CA_NAME, -1, -1, 0); + X509_NAME_add_entry_by_txt(s_name ,"CN" , MBSTRING_ASC, cname, -1, -1, 0); + + char subject_alt_name[MAX_ID_LEN] = {0}; + + sprintf(subject_alt_name, "DNS: %s", cname); + + X509_EXTENSION *extension_san = NULL; + ASN1_OCTET_STRING *subject_alt_name_ASN1 = NULL; + subject_alt_name_ASN1 = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(subject_alt_name_ASN1, (unsigned char*) subject_alt_name, strlen(subject_alt_name)); + X509_EXTENSION_create_by_NID(&extension_san, NID_subject_alt_name, 0, subject_alt_name_ASN1); + + BIO* pubkey = _keygen(4096); + + if(pubkey == NULL){ + + printf("keygen failed\n"); + + return -10; + } + + + pub_key_s = PEM_read_bio_PUBKEY(pubkey, NULL, NULL, NULL); + + FILE* fp = fopen(HUB_CA_PRIV, "r"); + + EVP_PKEY* priv_key_ca = PEM_read_PrivateKey(fp, NULL, NULL, NULL); + + fclose(fp); + + + if(ASN1_INTEGER_set(X509_get_serialNumber(x509_s), 420) == 0){ + printf("asn1 set serial number fail\n"); + } + + + if(X509_time_adj_ex(X509_getm_notBefore(x509_s), 0, 0, 0) == NULL){ + printf("set time fail\n"); + } + + if(X509_time_adj_ex(X509_getm_notAfter(x509_s), 0, 0, &exp_s) == NULL){ + printf("set end time fail\n"); + } + + X509_set_issuer_name(x509_s, ca_name); + X509_set_subject_name(x509_s, s_name); + + X509_add_ext(x509_s, extension_san, -1); + + //set public key + if(X509_set_pubkey(x509_s, pub_key_s) == 0){ + printf("set pubkey fail\n"); + } + + //sign certificate with private key + if(X509_sign(x509_s, priv_key_ca, EVP_sha256()) == 0){ + printf("sign fail\n"); + printf("Creating certificate failed...\n"); + } + + + fp = fopen("s.pem", "w"); + PEM_write_X509(fp, x509_s); + fclose(fp); +} + diff --git a/src/utils.c b/src/utils.c index 88b781f..8509963 100644 --- a/src/utils.c +++ b/src/utils.c @@ -39,7 +39,7 @@ int gen_random_bytestream(uint8_t* bytes, size_t num_bytes){ if(num_bytes > MAX_PW_LEN){ - return -1; + return -1; } @@ -48,7 +48,7 @@ int gen_random_bytestream(uint8_t* bytes, size_t num_bytes){ for (i = 0; i < num_bytes; i++){ - bytes[i] = rand(); + bytes[i] = rand(); } @@ -60,7 +60,6 @@ int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray){ int hexlen = 2; - int outstrlen = hexlen * arrlen + 1; if (outstrlen > MAX_PW_LEN){ @@ -83,6 +82,7 @@ int bin2hex(uint8_t* hexarray, int arrlen, uint8_t* bytearray){ memcpy(hexarray, tmparr, outstrlen); + free(tmparr); return 0; -- 2.43.0