Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add missing subscribe v2 crypto implementation #189

Merged
merged 5 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
name: c-core
schema: 1
version: "4.11.1"
version: "4.11.2"
scm: github.com/pubnub/c-core
changelog:
- date: 2024-07-15
version: v4.11.2
changes:
- type: bug
text: "Added missing subscribe v2 crypto implementation."
- date: 2024-06-28
version: v4.11.1
changes:
Expand Down Expand Up @@ -814,7 +819,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -880,7 +885,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -946,7 +951,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -1008,7 +1013,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -1069,7 +1074,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -1125,7 +1130,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down Expand Up @@ -1178,7 +1183,7 @@ sdks:
distribution-type: source code
distribution-repository: GitHub release
package-name: C-Core
location: https://github.com/pubnub/c-core/releases/tag/v4.11.1
location: https://github.com/pubnub/c-core/releases/tag/v4.11.2
requires:
-
name: "miniz"
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## v4.11.2
July 15 2024

#### Fixed
- Added missing subscribe v2 crypto implementation.

## v4.11.1
June 28 2024

Expand Down
8 changes: 4 additions & 4 deletions core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ pbcc_crypto_unittest: $(PROJECT_SOURCEFILES) $(CRYPTO_SOURCEFILES) pbcc_crypto_u
$(CGREEN_RUNNER) ./pbcc_crypto_unit_test.so
#$(GCOVR) -r . --html --html-details -o coverage.html

pubnub_crypto_unittest: $(PROJECT_SOURCEFILES) $(CRYPTO_SOURCEFILES) pubnub_crypto_unit_tests.c
gcc -o pubnub_crypto_unit_test.so -shared $(CFLAGS) $(LDFLAGS) $(CRYPTO_INCLUDES) $(CRYPTO_LIBS) -D PUBNUB_CRYPTO_API=1 -Wall $(COVERAGE_FLAGS) -fPIC $(PROJECT_SOURCEFILES) $(CRYPTO_SOURCEFILES) test/pubnub_test_mocks.c pubnub_crypto_unit_tests.c -lcgreen -lm
SUBSCRIBE_V2_SOURCEFILES += pubnub_subscribe_v2.c pbcc_subscribe_v2.c

pubnub_crypto_unittest: $(PROJECT_SOURCEFILES) $(CRYPTO_SOURCEFILES) $(SUBSCRIBE_V2_SOURCEFILES) pubnub_crypto_unit_tests.c
gcc -o pubnub_crypto_unit_test.so -shared $(CFLAGS) $(LDFLAGS) $(CRYPTO_INCLUDES) $(CRYPTO_LIBS) -D PUBNUB_CRYPTO_API=1 -D PUBNUB_USE_SUBSCRIBE_V2=1 -Wall $(COVERAGE_FLAGS) -fPIC $(PROJECT_SOURCEFILES) $(CRYPTO_SOURCEFILES) $(SUBSCRIBE_V2_SOURCEFILES) test/pubnub_test_mocks.c pubnub_crypto_unit_tests.c -lcgreen -lm
# gcc -o pubnub_core_unit_testo $(CFLAGS) -Wall $(COVERAGE_FLAGS) $(PROJECT_SOURCEFILES) pubnub_crypto_unit_tests.c -lcgreen -lm
$(CGREEN_RUNNER) ./pubnub_crypto_unit_test.so


SUBSCRIBE_V2_SOURCEFILES += pubnub_subscribe_v2.c pbcc_subscribe_v2.c

pubnub_subscribe_v2_unittest: $(PROJECT_SOURCEFILES) $(SUBSCRIBE_V2_SOURCEFILES) pubnub_subscribe_v2_unit_test.c
gcc -o pubnub_subscribe_v2_unit_test.so -shared $(CFLAGS) $(LDFLAGS) -D PUBNUB_ORIGIN_SETTABLE=1 -D PUBNUB_USE_SUBSCRIBE_V2=1 -Wall $(COVERAGE_FLAGS) -fPIC $(PROJECT_SOURCEFILES) $(SUBSCRIBE_V2_SOURCEFILES) test/pubnub_test_mocks.c pubnub_subscribe_v2_unit_test.c -lcgreen -lm
$(CGREEN_RUNNER) ./pubnub_subscribe_v2_unit_test.so
Expand Down
51 changes: 51 additions & 0 deletions core/pbcc_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,54 @@ void pbcc_set_crypto_module(struct pbcc_context *ctx, struct pubnub_crypto_provi
pubnub_crypto_provider_t *pbcc_get_crypto_module(struct pbcc_context *ctx) {
return ctx->crypto_module;
}

#if PUBNUB_CRYPTO_API
const char* pbcc_decrypt_message(struct pbcc_context *pb, const char* message, size_t len, size_t* out_len) {
char* trimmed = (char*)malloc(len + 1); // same length as message
if (NULL == trimmed) {
PUBNUB_LOG_ERROR("pbcc_get_msg(pbcc=%p) - failed to allocate memory for trimmed string. Returning original message!\n", pb);
return NULL;
}
snprintf(trimmed, len + 1, "%s", message);

trimmed[strlen(trimmed) - 1] = '\0';

pubnub_bymebl_t encrypted = pbcc_base64_decode(trimmed + 1);
free(trimmed);

if (NULL == encrypted.ptr) {
PUBNUB_LOG_WARNING("pbcc_get_msg(pbcc=%p) - base64 decoding failed. Returning original message!\n", pb);
if (NULL != out_len) {
*out_len = strlen(message);
}
return message;
}

pubnub_bymebl_t rslt_block = pb->crypto_module->decrypt(pb->crypto_module, encrypted);
free(encrypted.ptr);
if (NULL == rslt_block.ptr) {
PUBNUB_LOG_WARNING("pbcc_get_msg(pbcc=%p) - decryption failed. Returning original message!\n", pb);
if (NULL != out_len) {
*out_len = strlen(message);
}
return message;
}

if (pb->decrypted_message_count >= PUBNUB_MAX_DECRYPTED_MESSAGES) {
PUBNUB_LOG_ERROR("pbcc_get_msg(pbcc=%p) - maximum number of decrypted messages reached. Returning original message!\n", pb);
if (NULL != out_len) {
*out_len = 0;
}
return NULL;
}

pb->decrypted_messages[pb->decrypted_message_count] = rslt_block.ptr;
pb->decrypted_message_count++;

if (NULL != out_len) {
*out_len = rslt_block.size;
}

return (char*)rslt_block.ptr;
}
#endif /* PUBNUB_CRYPTO_API */
15 changes: 15 additions & 0 deletions core/pbcc_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,21 @@ void pbcc_set_crypto_module(struct pbcc_context *ctx, struct pubnub_crypto_provi
@return Pointer to the crypto provider used by the pubnub context.
*/
pubnub_crypto_provider_t *pbcc_get_crypto_module(struct pbcc_context *ctx);

#if PUBNUB_CRYPTO_API
/**
Decrypt the message received from PubNub with the crypto module.

This function takes the message received from PubNub and decrypts it
for the user. It uses the crypto module used by the pubnub context.

@param pubnub Pointer to the pubnub context.
@param message The message received from PubNub.

@return The decrypted message or NULL on error.
*/
const char* pbcc_decrypt_message(struct pbcc_context *ctx, const char* message, size_t len, size_t* out_len);
#endif /* PUBNUB_CRYPTO_API */


#endif /* PBCC_CRYPTO_H */
22 changes: 22 additions & 0 deletions core/pbcc_subscribe_v2.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */

#include "pbcc_crypto.h"
#if PUBNUB_USE_SUBSCRIBE_V2

#include "pubnub_internal.h"
Expand Down Expand Up @@ -55,6 +56,13 @@ enum pubnub_res pbcc_subscribe_v2_prep(struct pbcc_context* p,
p->http_content_len = 0;
p->msg_ofs = p->msg_end = 0;

#if PUBNUB_CRYPTO_API
for (size_t i = 0; i < p->decrypted_message_count; i++) {
free(p->decrypted_messages[i]);
}
p->decrypted_message_count = 0;
#endif

p->http_buf_len = snprintf(
p->http_buf, sizeof p->http_buf, "/v2/subscribe/%s/", p->subscribe_key);
APPEND_URL_ENCODED_M(p, channel);
Expand Down Expand Up @@ -212,12 +220,15 @@ struct pubnub_v2_message pbcc_get_msg_v2(struct pbcc_context* p)
}
PUBNUB_LOG_DEBUG("RESPONSE = %s\n", p->http_reply);
start = p->http_reply + p->msg_ofs;

if (*start != '{') {
PUBNUB_LOG_ERROR(
"Message subscribe V2 response is not a JSON object\n");
return rslt;
}

end = p->http_reply + p->msg_end;

seeker = pbjson_find_end_complex(start, end);
if (seeker == end) {
PUBNUB_LOG_ERROR(
Expand All @@ -235,8 +246,19 @@ struct pubnub_v2_message pbcc_get_msg_v2(struct pbcc_context* p)

jpresult = pbjson_get_object_value(&el, "d", &found);
if (jonmpOK == jpresult) {
#if PUBNUB_CRYPTO_API
if (NULL != p->crypto_module) {
rslt.payload.ptr = (char*)pbcc_decrypt_message(
p,
(char*)found.start,
found.end - found.start,
&rslt.payload.size
);
}
#else
rslt.payload.ptr = (char*)found.start;
rslt.payload.size = found.end - found.start;
#endif /* PUBNUB_CRYPTO_API */
}
else {
PUBNUB_LOG_ERROR("pbcc=%p: No message payload in subscribe V2 response "
Expand Down
41 changes: 6 additions & 35 deletions core/pubnub_ccore_pubsub.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,49 +113,20 @@ bool pbcc_ensure_reply_buffer(struct pbcc_context* p)

char const* pbcc_get_msg(struct pbcc_context* pb)
{
#if PUBNUB_CRYPTO_API
size_t len;
#endif // PUBNUB_CRYPTO_API
if (pb->msg_ofs < pb->msg_end) {
PUBNUB_LOG_DEBUG("RESPONSE = %s\n", pb->http_reply);
char const* rslt = pb->http_reply + pb->msg_ofs;
pb->msg_ofs += strlen(rslt);
if (pb->msg_ofs++ <= pb->msg_end) {
#if PUBNUB_CRYPTO_API
if (NULL != pb->crypto_module) {
char* trimmed = (char*)malloc(strlen(rslt) + 1); // same length as rslt
if (NULL == trimmed) {
PUBNUB_LOG_ERROR("pbcc_get_msg(pbcc=%p) - failed to allocate memory for trimmed string. Returning original message!\n", pb);
return NULL;
}
sprintf(trimmed, "%s", rslt);

trimmed[strlen(trimmed) - 1] = '\0';

pubnub_bymebl_t encrypted = pbcc_base64_decode(trimmed + 1);
free(trimmed);

if (NULL == encrypted.ptr) {
PUBNUB_LOG_WARNING("pbcc_get_msg(pbcc=%p) - base64 decoding failed. Returning original message!\n", pb);
return rslt;
}

pubnub_bymebl_t rslt_block = pb->crypto_module->decrypt(pb->crypto_module, encrypted);
free(encrypted.ptr);
if (NULL == rslt_block.ptr) {
PUBNUB_LOG_WARNING("pbcc_get_msg(pbcc=%p) - decryption failed. Returning original message!\n", pb);
return rslt;
}

if (pb->decrypted_message_count >= PUBNUB_MAX_DECRYPTED_MESSAGES) {
PUBNUB_LOG_ERROR("pbcc_get_msg(pbcc=%p) - maximum number of decrypted messages reached. Returning original message!\n", pb);
return NULL;
}

pb->decrypted_messages[pb->decrypted_message_count] = rslt_block.ptr;
pb->decrypted_message_count++;

rslt = (char*)rslt_block.ptr;
if (pb->crypto_module != NULL) {
len = strlen(rslt);
rslt = pbcc_decrypt_message(pb, rslt, len, NULL);
}
#endif // PUBNUB_CRYPTO_API

return rslt;
}
}
Expand Down
43 changes: 43 additions & 0 deletions core/pubnub_crypto_unit_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "cgreen/cgreen.h"
#include "cgreen/constraint_syntax_helpers.h"
#include "cgreen/mocks.h"
#include "pubnub_coreapi_ex.h"
#include "pubnub_helper.h"
#include "pubnub_memory_block.h"
#include "test/pubnub_test_mocks.h"

Expand All @@ -18,6 +20,8 @@
#include "pubnub_coreapi.h"
#include "pubnub_crypto.h"
#include "pbcc_crypto.h"
#include "pubnub_subscribe_v2.h"
#include "pubnub_subscribe_v2_message.h"
#include <stdint.h>
#include <stdlib.h>

Expand Down Expand Up @@ -167,6 +171,45 @@ Ensure(crypto_api, client_should_use_cryptors_for_history) {
assert_that(pubnub_last_http_code(pbp), is_equal_to(200));
}

Ensure(crypto_api, client_should_use_cryptors_for_subscribe_v2) {
pubnub_set_crypto_module(pbp, pubnub_crypto_module_init(&x_cryptor, &y_cryptor, 1));

assert_that(pubnub_last_time_token(pbp), is_equal_to_string("0"));
expect_have_dns_for_pubnub_origin_on_ctx(pbp);
expect_outgoing_with_url_no_params_on_ctx(pbp,
"/v2/subscribe/sub_key/my-channel/0");
incoming("HTTP/1.1 200\r\nContent-Length: "
"44\r\n\r\n{\"t\":{\"t\":\"15628652479932717\",\"r\":4},\"m\":[]}",
NULL);
expect(pbntf_lost_socket, when(pb, is_equal_to(pbp)));
expect(pbntf_trans_outcome, when(pb, is_equal_to(pbp)));
assert_that(pubnub_subscribe_v2(pbp, "my-channel", pubnub_subscribe_v2_defopts()), is_equal_to(PNR_OK));

assert_that(pubnub_get(pbp), is_equal_to(NULL));
assert_that(pubnub_last_http_code(pbp), is_equal_to(200));
assert_that(pubnub_last_time_token(pbp), is_equal_to_string("15628652479932717"));
/* Not publish operation */
assert_that(pubnub_last_publish_result(pbp), is_equal_to_string(""));

expect(pbntf_enqueue_for_processing, when(pb, is_equal_to(pbp)), will_return(0));
expect(pbntf_got_socket, when(pb, is_equal_to(pbp)), will_return(0));
expect_outgoing_with_url_no_params_on_ctx(pbp,
"/v2/subscribe/sub_key/my-channel/0");
incoming("HTTP/1.1 200\r\nContent-Length: "
"198\r\n\r\n{\"t\":{\"t\":\"15628652479932717\",\"r\":4},\"m\":[{\"a\":\"1\",\"f\":514,\"i\":\"publisher_id\",\"s\":1,\"p\":{\"t\":\"15628652479933927\",\"r\":4},\"k\":\"demo\",\"c\":\"my-channel\",\"d\":\"UE5FRAF4eHh4BG1ldGF4eHh4\",\"b\":\"my-channel\"}]}",
NULL);
expect(pbntf_lost_socket, when(pb, is_equal_to(pbp)));
expect(pbntf_trans_outcome, when(pb, is_equal_to(pbp)));
assert_that(pubnub_subscribe_v2(pbp, "my-channel", pubnub_subscribe_v2_defopts()), is_equal_to(PNR_OK));
assert_that(pubnub_last_time_token(pbp), is_equal_to_string("15628652479932717"));

struct pubnub_v2_message msg = pubnub_get_v2(pbp);
assert_that(msg.payload.ptr, is_equal_to_string(X));
assert_that(pubnub_get_v2(pbp).payload.ptr, is_equal_to(NULL));
assert_that(pubnub_last_http_code(pbp), is_equal_to(200));
}


int x_encrypt(pubnub_cryptor_t const* _c, struct pubnub_encrypted_data *result, pubnub_bymebl_t _d) {
result->data.ptr = (uint8_t*)X;
result->data.size = X_SIZE;
Expand Down
2 changes: 1 addition & 1 deletion core/pubnub_version_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#define INC_PUBNUB_VERSION_INTERNAL


#define PUBNUB_SDK_VERSION "4.11.1"
#define PUBNUB_SDK_VERSION "4.11.2"


#endif /* !defined INC_PUBNUB_VERSION_INTERNAL */
Loading