From 1c60f4990e20febc41201ae1b3a9aca5b5de65ac Mon Sep 17 00:00:00 2001 From: Richard Bayerle Date: Sat, 22 Jan 2022 11:55:52 +0100 Subject: [PATCH] fix example code and some memory leaks (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this closes #14, as it is a manual merge of the changes, plus some minor additions like gitignore and changelog entries. commit 78cb8705befd1937c31133a2b27535f6e8a89475 Author: Richard Bayerle Date: Sat Jan 22 11:51:46 2022 +0100 add changelog entry commit 079cdb71daf801cbee857e37fb5b8b25dc1fcbcc Author: Richard Bayerle Date: Sat Jan 22 11:45:40 2022 +0100 add client dir to gitignore commit e2e6647e68aa5d7b8c8b7a28b502376a7c0ac99d Merge: 3872bcc c77b01c Author: Richard Bayerle Date: Sat Jan 22 11:41:09 2022 +0100 Merge branch 'fix-msg-client' of https://github.com/fbrausse/axc into fbrausse-fix-msg-client commit c77b01c00edfcf66ef0b61ef9e6ecbe392eec3bd Author: Franz Brauße Date: Mon Jul 29 02:56:18 2019 +0200 src/message_client: simplify by FAIL macros commit 54e8c17a3a198d4a69b4d50b9d8fc01b943dc91a Author: Franz Brauße Date: Thu Aug 1 12:09:00 2019 +0200 src/message_client: remove old commented handshake-based init code commit 5e4abed1bed7c40a586198fa27021c8d45a19efe Author: Franz Brauße Date: Sun Jul 28 21:29:57 2019 +0200 src/message_client: fix break loop on ^D + print newline on exit commit 4187e64892aacf13c1b0254a42eb0fb37594967c Author: Franz Brauße Date: Sun Jul 28 21:22:28 2019 +0200 src/message_client: fix resuming session: retrieve alice's device_id commit 9ba4bb42529d5c2467d3882bd725730d98c77f0a Author: Franz Brauße Date: Sun Jul 28 20:55:42 2019 +0200 src/message_client: fix compiler warnings about casts between uint8_t * and char * commit 960429ce9e80f78a9f3c7ccae09fb9657b066243 Author: Franz Brauße Date: Sun Jul 28 20:51:31 2019 +0200 axc: fix memory leaks commit 2cafb157a9f811d208bedd6ce480b3715bc93558 Author: Franz Brauße Date: Sun Jul 28 20:51:06 2019 +0200 message_client: fix compile errors + fix memory leaks Co-authored-by: Franz Brauße Co-authored-by: Richard Bayerle --- .gitignore | 1 + CHANGELOG.md | 2 + src/axc.c | 6 +- src/axc_crypto.c | 1 + src/axc_store.c | 3 +- src/message_client.c | 194 ++++++++++++++++++++++--------------------- 6 files changed, 110 insertions(+), 97 deletions(-) diff --git a/.gitignore b/.gitignore index 29923bf..58f6e18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ +client/ lib/libaxolotl-c/build *.gc* *.o diff --git a/CHANGELOG.md b/CHANGELOG.md index ca603a0..82f7d3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - Compiler warnings ([#21](https://github.com/gkdr/axc/issues/21), [#29](https://github.com/gkdr/axc/pull/29)) (thanks, [@hartwork](https://github.com/hartwork)!) - `gcc` can now be set from env like the rest of the tools. ([#30](https://github.com/gkdr/axc/pull/30))) (thanks, [@henry-nicolas](https://github.com/henry-nicolas) and Helmut Grohne!) - Fix the build for users without libsignal-protocol-c installed system-wide ([#31](https://github.com/gkdr/axc/pull/31)) (thanks, [@hartwork](https://github.com/hartwork)!) +- The example code is runnable again, and some memory leaks ([#14](https://github.com/gkdr/axc/pull/14)) (thanks, [@fbrausse](https://github.com/fbrausse)!) + ### Infrastructure - Cover Linux build by GitHub Actions CI ([#31](https://github.com/gkdr/axc/pull/31)) (thanks, [@hartwork](https://github.com/hartwork)!) diff --git a/src/axc.c b/src/axc.c index 35f315e..e78b83a 100644 --- a/src/axc.c +++ b/src/axc.c @@ -243,6 +243,7 @@ void axc_bundle_destroy(axc_bundle * bundle_p) { axc_buf_free(bundle_p->signed_pre_key_public_serialized_p); axc_buf_free(bundle_p->signed_pre_key_signature_p); axc_buf_free(bundle_p->identity_key_public_serialized_p); + free(bundle_p); } } @@ -423,7 +424,6 @@ void axc_context_destroy_all(axc_context * ctx_p) { axc_mutexes_destroy(ctx_p->mutexes_p); free(ctx_p->db_filename); - free(ctx_p); } } @@ -1104,6 +1104,10 @@ int axc_pre_key_message_process(axc_buf * pre_key_msg_serialized_p, axc_address do { + if (key_l_p) { + signal_protocol_key_helper_key_list_free(key_l_p); + key_l_p = NULL; + } ret_val = signal_protocol_key_helper_generate_pre_keys(&key_l_p, new_id, 1, ctx_p->axolotl_global_context_p); if (ret_val) { err_msg = "failed to generate a new key"; diff --git a/src/axc_crypto.c b/src/axc_crypto.c index 4e02923..de5f87b 100644 --- a/src/axc_crypto.c +++ b/src/axc_crypto.c @@ -390,6 +390,7 @@ int aes_encrypt(signal_buffer ** output_pp, } } + free(pt_p); free(out_p); gcry_cipher_close(cipher_hd); diff --git a/src/axc_store.c b/src/axc_store.c index 1cdf84d..910dc18 100644 --- a/src/axc_store.c +++ b/src/axc_store.c @@ -764,6 +764,7 @@ int axc_db_pre_key_get_list(size_t amount, axc_context * axc_ctx_p, axc_buf_list } *list_head_pp = axc_buf_list_item_get_next(head_p); + axc_buf_list_item_set_next(head_p, NULL); ret_val = 0; cleanup: @@ -771,8 +772,8 @@ int axc_db_pre_key_get_list(size_t amount, axc_context * axc_ctx_p, axc_buf_list axc_buf_free(serialized_keypair_data_p); SIGNAL_UNREF(pre_key_p); axc_buf_free(pre_key_public_serialized_p); - axc_buf_list_free(head_p); } + axc_buf_list_free(head_p); db_conn_cleanup(db_p, pstmt_p, err_msg, __func__, axc_ctx_p); return ret_val; diff --git a/src/message_client.c b/src/message_client.c index 99909bb..0b62146 100644 --- a/src/message_client.c +++ b/src/message_client.c @@ -8,77 +8,55 @@ #include // toupper #include // printf, getline #include // exit codes -#include // socket -#include // socket -#include // getaddrinfo #include // memset, strlen -#include // write - -#include "axolotl.h" #include "axc.h" -#define PORT "5555" +#define FAIL0(lbl,...) do { ret = EXIT_FAILURE; fprintf(stderr, __VA_ARGS__); goto lbl; } while (0) +#define FAIL(...) FAIL0(cleanup,__VA_ARGS__) int main(void) { printf("sup\n"); printf("initializing context for alice...\n"); axc_context * ctx_a_p; - if (axc_context_create(&ctx_a_p)) { - fprintf(stderr, "failed to create axc context\n"); - return EXIT_FAILURE; - } + int ret = EXIT_SUCCESS; + if (axc_context_create(&ctx_a_p)) + FAIL0(cleanup_none, "failed to create axc context\n"); axc_context_set_log_func(ctx_a_p, axc_default_log); axc_context_set_log_level(ctx_a_p, AXC_LOG_DEBUG); char * db_a_fn = "client/a.sqlite"; - if (axc_context_set_db_fn(ctx_a_p, db_a_fn, strlen(db_a_fn))) { - fprintf(stderr, "failed to set db filename\n"); - return EXIT_FAILURE; - } + if (axc_context_set_db_fn(ctx_a_p, db_a_fn, strlen(db_a_fn))) + FAIL0(cleanup_a, "failed to set db filename\n"); printf("set db fn\n"); - if (axc_init(ctx_a_p)) { - fprintf(stderr, "failed to init axc\n"); - return EXIT_FAILURE; - } + if (axc_init(ctx_a_p)) + FAIL0(cleanup_a, "failed to init axc\n"); printf("installing client for alice...\n"); - if (axc_install(ctx_a_p)) { - fprintf(stderr, "failed to install axc\n"); - axc_cleanup(ctx_a_p); - return EXIT_FAILURE; - } + if (axc_install(ctx_a_p)) + FAIL0(cleanup_a, "failed to install axc\n"); printf("initializing context for bob...\n"); axc_context * ctx_b_p; - if (axc_context_create(&ctx_b_p)) { - fprintf(stderr, "failed to create axc context\n"); - return EXIT_FAILURE; - } + if (axc_context_create(&ctx_b_p)) + FAIL0(cleanup_a, "failed to create axc context\n"); char * db_b_fn = "client/b.sqlite"; - if (axc_context_set_db_fn(ctx_b_p, db_b_fn, strlen(db_b_fn))) { - fprintf(stderr, "failed to set db filename\n"); - return EXIT_FAILURE; - } + if (axc_context_set_db_fn(ctx_b_p, db_b_fn, strlen(db_b_fn))) + FAIL("failed to set db filename\n"); axc_context_set_log_func(ctx_b_p, axc_default_log); axc_context_set_log_level(ctx_b_p, AXC_LOG_DEBUG); - if (axc_init(ctx_b_p)) { - fprintf(stderr, "failed to init axc\n"); - return EXIT_FAILURE; - } + if (axc_init(ctx_b_p)) + FAIL("failed to init axc\n"); printf("installing client for bob...\n"); - if (axc_install(ctx_b_p)) { - fprintf(stderr, "failed to install axc\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + if (axc_install(ctx_b_p)) + FAIL("failed to install axc\n"); axc_address addr_a = { .name = "alice", @@ -95,100 +73,126 @@ int main(void) { printf("checking if session already exists\n"); if (!axc_session_exists_initiated(&addr_b, ctx_a_p)) { printf("creating session between alice and bob\n"); - printf("creating handshake initiation message\n"); - axc_handshake * handshake_a; - if (axc_handshake_initiate(&addr_b, ctx_a_p, &handshake_a)) { - fprintf(stderr, "failed to initialize handshake from alice to bob\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } - - printf("'sending' the message to bob and accepting it\n"); - axc_handshake * handshake_b; - if (axc_handshake_accept(axc_handshake_get_data(handshake_a), &addr_a, ctx_b_p, &handshake_b)) { - fprintf(stderr, "failed to accept handshake on bob's side\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } - - printf("'sending' response from bob back to alice\n"); - if (axc_handshake_acknowledge(axc_handshake_get_data(handshake_b), handshake_a, ctx_a_p)) { - fprintf(stderr, "failed to acknowledge handhshake on alice' side\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + axc_bundle *bundle_bob; + if (axc_bundle_collect(AXC_PRE_KEYS_AMOUNT, ctx_b_p, &bundle_bob)) + FAIL("failed to collect bob's bundle\n"); + // addr_b.device_id = axc_bundle_get_reg_id(bundle_bob); + if (axc_session_from_bundle(axc_buf_list_item_get_id(axc_bundle_get_pre_key_list(bundle_bob)), + axc_buf_list_item_get_buf(axc_bundle_get_pre_key_list(bundle_bob)), + axc_bundle_get_signed_pre_key_id(bundle_bob), + axc_bundle_get_signed_pre_key(bundle_bob), + axc_bundle_get_signature(bundle_bob), + axc_bundle_get_identity_key(bundle_bob), + &addr_b, + ctx_a_p)) + FAIL("failed to create session from bob's bundle\n"); + axc_bundle_destroy(bundle_bob); + axc_buf * msg_buf_p = axc_buf_create((const uint8_t *)"hello", strlen("hello") + 1); + if (!msg_buf_p) + FAIL("failed to create 'hello' msg buffer\n"); + + axc_buf * ct_buf_p; + if (axc_message_encrypt_and_serialize(msg_buf_p, &addr_b, ctx_a_p, &ct_buf_p)) + FAIL("failed to encrypt 'hello' message\n"); + + uint32_t alice_id; + if (axc_get_device_id(ctx_a_p, &alice_id)) + FAIL("failed to retrieve alice's device_id\n"); + addr_a.device_id = alice_id; + + axc_buf * pt_buf_p; + if (axc_pre_key_message_process(ct_buf_p, &addr_a, ctx_b_p, &pt_buf_p)) + FAIL("failed to process 'hello' pre_key_message\n"); + + axc_buf_free(ct_buf_p); + axc_buf_free(pt_buf_p); + + if (axc_message_encrypt_and_serialize(msg_buf_p, &addr_a, ctx_b_p, &ct_buf_p)) + FAIL("failed encrypting 2nd 'hello' message\n"); + if (axc_message_decrypt_from_serialized(ct_buf_p, &addr_b, ctx_a_p, &pt_buf_p)) + FAIL("failed decrypting 2nd 'hello' message\n"); + + axc_buf_free(ct_buf_p); + axc_buf_free(pt_buf_p); + axc_buf_free(msg_buf_p); printf("session created on each side\n"); } else { printf("session exists.\n"); + uint32_t alice_id; + if (axc_get_device_id(ctx_a_p, &alice_id)) + FAIL("failed to retrieve alice's device_id\n"); + addr_a.device_id = alice_id; } printf("now trying to ready to 'send' and 'receive' messages\n"); char * line = (void *) 0; size_t len = 0; printf("enter message: "); - //goto cleanup; - while(getline(&line, &len, stdin)) { + while(getline(&line, &len, stdin) > 0) { axc_buf * ciphertext_p; + { axc_buf * msg_p = axc_buf_create((uint8_t *) line, strlen(line) + 1); - if (axc_message_encrypt_and_serialize(msg_p, &addr_b, ctx_a_p, &ciphertext_p)) { - fprintf(stderr, "failed to encrypt message from alice to bob\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + if (axc_message_encrypt_and_serialize(msg_p, &addr_b, ctx_a_p, &ciphertext_p)) + FAIL("failed to encrypt message from alice to bob\n"); printf("encrypted message from alice to bob: %s\n", line); + axc_buf_free(msg_p); + } - uint8_t * buf = axolotl_buffer_data(ciphertext_p); + uint8_t * buf = signal_buffer_data(ciphertext_p); - printf("ciphertext:\n"); + printf("serialized ciphertext (hex):\n"); for (size_t i = 0; i < axc_buf_get_len(ciphertext_p); i++) { - printf("0x%02X ", buf[i]); + printf("%02X ", buf[i]); } printf("\n"); + axc_buf * upper_buf; axc_buf * plaintext_p; - if (axc_message_decrypt_from_serialized(ciphertext_p, &addr_a, ctx_b_p, &plaintext_p)) { - fprintf(stderr, "failed to decrypt message from alice to bob\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + if (axc_message_decrypt_from_serialized(ciphertext_p, &addr_a, ctx_b_p, &plaintext_p)) + FAIL("failed to decrypt message from alice to bob\n"); + axc_buf_free(ciphertext_p); printf("decrypted message: %s\n", axc_buf_get_data(plaintext_p)); - char * upper = axc_buf_get_data(plaintext_p); + char * upper = (char *)axc_buf_get_data(plaintext_p); for (size_t i = 0; i < strlen(upper); i++) { upper[i] = toupper(upper[i]); } printf("bob sending reply...\n"); - axc_buf * upper_buf = axc_buf_create((uint8_t *) upper, strlen(upper) + 1); + upper_buf = axc_buf_create((uint8_t *) upper, strlen(upper) + 1); + axc_buf_free(plaintext_p); - if (axc_message_encrypt_and_serialize(upper_buf, &addr_a, ctx_b_p, &ciphertext_p)) { - fprintf(stderr, "failed to encrypt message from bob to alice\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + if (axc_message_encrypt_and_serialize(upper_buf, &addr_a, ctx_b_p, &ciphertext_p)) + FAIL("failed to encrypt message from bob to alice\n"); + axc_buf_free(upper_buf); - buf = axolotl_buffer_data(ciphertext_p); + buf = signal_buffer_data(ciphertext_p); - printf("ciphertext:\n"); + printf("serialized ciphertext (hex):\n"); for (size_t i = 0; i < axc_buf_get_len(ciphertext_p); i++) { - printf("0x%02X ", buf[i]); + printf("%02X ", buf[i]); } printf("\n"); - if (axc_message_decrypt_from_serialized(ciphertext_p, &addr_b, ctx_a_p, &plaintext_p)) { - fprintf(stderr, "failed to decrypt message from bob to alice\n"); - axc_cleanup(ctx_b_p); - return EXIT_FAILURE; - } + if (axc_message_decrypt_from_serialized(ciphertext_p, &addr_b, ctx_a_p, &plaintext_p)) + FAIL("failed to decrypt message from bob to alice\n"); + axc_buf_free(ciphertext_p); printf("received reply from bob: %s\n", axc_buf_get_data(plaintext_p)); + axc_buf_free(plaintext_p); printf("enter message: "); } + free(line); - printf("done, exiting."); - axc_cleanup(ctx_a_p); + printf("done, exiting.\n"); + +cleanup: axc_cleanup(ctx_b_p); +cleanup_a: + axc_cleanup(ctx_a_p); +cleanup_none: + return ret; }