diff --git a/.ci/adjust-config.sh b/.ci/adjust-config.sh index 8f2111376284af7e74d12e6e4121e17050db8c8a..6f223e1b807c6dd31cdc7b8e68614affeeeb5b83 100755 --- a/.ci/adjust-config.sh +++ b/.ci/adjust-config.sh @@ -13,28 +13,38 @@ $CMD perl -pi -w -e \ ( cat <<HEREDOC + + rc_message: - per_second: 1000 - burst_count: 10000 + per_second: 10000 + burst_count: 100000 rc_registration: - per_second: 1000 - burst_count: 3000 + per_second: 10000 + burst_count: 30000 rc_login: address: - per_second: 1000 - burst_count: 3000 + per_second: 10000 + burst_count: 30000 account: - per_second: 1000 - burst_count: 3000 + per_second: 10000 + burst_count: 30000 failed_attempts: - per_second: 1000 - burst_count: 3000 + per_second: 10000 + burst_count: 30000 rc_admin_redaction: per_second: 1000 burst_count: 5000 + +rc_joins: + local: + per_second: 10000 + burst_count: 100000 + remote: + per_second: 10000 + burst_count: 100000 HEREDOC ) | $CMD tee -a data/homeserver.yaml diff --git a/Makefile b/Makefile index 97eba7fb2699f9981ef817d940f9c333b16f2334..92805e07b551d66fe202557e70cdf656227158f3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ FILES=`find lib include tests examples -type f -type f \( -iname "*.cpp" -o -iname "*.hpp" \)` -SYNAPSE_IMAGE="matrixdotorg/synapse:v1.7.2" +SYNAPSE_IMAGE="matrixdotorg/synapse:v1.24.0" DEPS_BUILD_DIR=.deps DEPS_SOURCE_DIR=deps diff --git a/include/mtx/events/collections.hpp b/include/mtx/events/collections.hpp index 449ea3193f7efe24261f3cb3c51ed42cb2d95c5e..5378f1af3b362372545bc48e416c1a047a520043 100644 --- a/include/mtx/events/collections.hpp +++ b/include/mtx/events/collections.hpp @@ -57,7 +57,9 @@ using DeviceEvents = std::variant<events::DeviceEvent<msgs::RoomKey>, events::DeviceEvent<msgs::KeyVerificationAccept>, events::DeviceEvent<msgs::KeyVerificationCancel>, events::DeviceEvent<msgs::KeyVerificationKey>, - events::DeviceEvent<msgs::KeyVerificationMac>>; + events::DeviceEvent<msgs::KeyVerificationMac>, + events::DeviceEvent<msgs::SecretRequest>, + events::DeviceEvent<msgs::SecretSend>>; //! Collection of room specific account data using RoomAccountDataEvents = @@ -279,5 +281,11 @@ constexpr inline EventType to_device_content_to_type<mtx::events::msg::KeyVerifi template<> constexpr inline EventType to_device_content_to_type<mtx::events::msg::KeyVerificationMac> = EventType::KeyVerificationMac; +template<> +constexpr inline EventType to_device_content_to_type<mtx::events::msg::SecretSend> = + EventType::SecretSend; +template<> +constexpr inline EventType to_device_content_to_type<mtx::events::msg::SecretRequest> = + EventType::SecretRequest; } // namespace events } // namespace mtx diff --git a/include/mtx/events/encrypted.hpp b/include/mtx/events/encrypted.hpp index 625bc747d6fb7760f1dcf72ceb227c71fa0d10a9..7c2babe980ad4a4e7d251a6aeceb9fc0c248dc39 100644 --- a/include/mtx/events/encrypted.hpp +++ b/include/mtx/events/encrypted.hpp @@ -395,6 +395,41 @@ from_json(const nlohmann::json &obj, KeyVerificationMac &event); void to_json(nlohmann::json &obj, const KeyVerificationMac &event); +struct SecretRequest +{ + //! The type of request. + RequestAction action; + + //! Required if action is request. The name of the secret that is being requested. + std::string name; + + //! A unique identifier for this request. + std::string request_id; + //! The device requesting the keys. + std::string requesting_device_id; +}; + +void +from_json(const nlohmann::json &obj, SecretRequest &event); + +void +to_json(nlohmann::json &obj, const SecretRequest &event); + +struct SecretSend +{ + //! Required. The contents of the secret. + std::string secret; + + //! A unique identifier for this request. + std::string request_id; +}; + +void +from_json(const nlohmann::json &obj, SecretSend &event); + +void +to_json(nlohmann::json &obj, const SecretSend &event); + } // namespace msg } // namespace events } // namespace mtx diff --git a/include/mtx/events/event_type.hpp b/include/mtx/events/event_type.hpp index 8ef332721bd57a8cba3313b8a95be7692d82a159..2a8fd4559cb2336e7a2728ec14346f051f0cda03 100644 --- a/include/mtx/events/event_type.hpp +++ b/include/mtx/events/event_type.hpp @@ -87,6 +87,11 @@ enum class EventType // m.call.hangup CallHangUp, + // m.secret.request + SecretRequest, + // m.secret.send + SecretSend, + // custom events // im.nheko.hidden_events NhekoHiddenEvents, diff --git a/include/mtxclient/crypto/client.hpp b/include/mtxclient/crypto/client.hpp index 1476743d3814b23d2e5b807b573ef83556ec3a9d..4b2934f773363d51b08d39dad6116f226c91e8c0 100644 --- a/include/mtxclient/crypto/client.hpp +++ b/include/mtxclient/crypto/client.hpp @@ -45,6 +45,10 @@ public: : msg_(func + ": " + std::string(olm_pk_decryption_last_error(s))) {} + olm_exception(std::string func, OlmPkSigning *s) + : msg_(func + ": " + std::string(olm_pk_signing_last_error(s))) + {} + olm_exception(std::string func, OlmOutboundGroupSession *s) : msg_(func + ": " + std::string(olm_outbound_group_session_last_error(s))) {} @@ -114,6 +118,21 @@ private: SASPtr sas; }; +struct PkSigning +{ + //! Construct from base64 key + static PkSigning from_seed(std::string seed); + std::string sign(const std::string &message); + + //! base64 public key + std::string public_key() const { return public_key_; } + +private: + PkSigning() {} + std::unique_ptr<OlmPkSigning, OlmDeleter> signing; + std::string public_key_; +}; + class OlmClient : public std::enable_shared_from_this<OlmClient> { public: diff --git a/include/mtxclient/crypto/objects.hpp b/include/mtxclient/crypto/objects.hpp index a0fa155a27b8e5ff206dc38d3da3d4ef28d35b42..9303940dfc333ef626242bf122b9e0d6ce4bd4f9 100644 --- a/include/mtxclient/crypto/objects.hpp +++ b/include/mtxclient/crypto/objects.hpp @@ -14,6 +14,7 @@ struct OlmDeleter void operator()(OlmUtility *ptr) { delete[](reinterpret_cast<uint8_t *>(ptr)); } void operator()(OlmPkDecryption *ptr) { delete[](reinterpret_cast<uint8_t *>(ptr)); } + void operator()(OlmPkSigning *ptr) { delete[](reinterpret_cast<uint8_t *>(ptr)); } void operator()(OlmSession *ptr) { delete[](reinterpret_cast<uint8_t *>(ptr)); } void operator()(OlmOutboundGroupSession *ptr) @@ -48,6 +49,13 @@ struct PkDecryptionObject } }; +struct PkSigningObject +{ + using olm_type = OlmPkSigning; + + static olm_type *allocate() { return olm_pk_signing(new uint8_t[olm_pk_signing_size()]); } +}; + struct AccountObject { using olm_type = OlmAccount; diff --git a/lib/crypto/client.cpp b/lib/crypto/client.cpp index baed4e35b201abeace1b505923eff3013ee411a1..53b1ae4a426d81b8c46645cd2b0ef84efb1b7a41 100644 --- a/lib/crypto/client.cpp +++ b/lib/crypto/client.cpp @@ -529,6 +529,44 @@ SAS::calculate_mac(std::string input_data, std::string info) return to_string(output_buffer); } +PkSigning +PkSigning::from_seed(std::string seed) +{ + PkSigning s{}; + s.signing = create_olm_object<PkSigningObject>(); + + auto seed_ = base642bin(seed); + + auto pub_key_buffer = BinaryBuf(olm_pk_signing_public_key_length()); + auto ret = olm_pk_signing_key_from_seed(s.signing.get(), + pub_key_buffer.data(), + pub_key_buffer.size(), + seed_.data(), + seed_.size()); + + if (ret == olm_error()) + throw olm_exception("signing_from_seed", s.signing.get()); + + s.public_key_ = to_string(pub_key_buffer); + + return s; +} + +std::string +PkSigning::sign(const std::string &message) +{ + auto signature = BinaryBuf(olm_pk_signature_length()); + auto message_ = to_binary_buf(message); + + auto ret = olm_pk_sign( + signing.get(), message_.data(), message_.size(), signature.data(), signature.size()); + + if (ret == olm_error()) + throw olm_exception("olm_pk_sign", signing.get()); + + return to_string(signature); +} + nlohmann::json OlmClient::create_olm_encrypted_content(OlmSession *session, nlohmann::json event, diff --git a/lib/http/client.cpp b/lib/http/client.cpp index d3f29975aba97e6f03a392c44dd3d955bb25562b..32bd363f0620d1a3e2c1dbfdfca6494584d0420c 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -1248,3 +1248,5 @@ MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationAccept) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationCancel) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationKey) MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::KeyVerificationMac) +MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::SecretSend) +MTXCLIENT_SEND_TO_DEVICE(mtx::events::msg::SecretRequest) diff --git a/lib/structs/events.cpp b/lib/structs/events.cpp index 9be4a2241fe29eb958e2ebdb2969124c7e9358f8..0a65c88a303300a6d17fd2f50a4b1be4720bbc74 100644 --- a/lib/structs/events.cpp +++ b/lib/structs/events.cpp @@ -84,6 +84,10 @@ getEventType(const std::string &type) return EventType::CallAnswer; else if (type == "m.call.hangup") return EventType::CallHangUp; + else if (type == "m.secret.request") + return EventType::SecretRequest; + else if (type == "m.secret.send") + return EventType::SecretSend; else if (type == "im.nheko.hidden_events") return EventType::NhekoHiddenEvents; else @@ -168,6 +172,10 @@ to_string(EventType type) return "m.call.answer"; case EventType::CallHangUp: return "m.call.hangup"; + case EventType::SecretRequest: + return "m.secret.request"; + case EventType::SecretSend: + return "m.secret.send"; case EventType::NhekoHiddenEvents: return "im.nheko.hidden_events"; case EventType::Unsupported: diff --git a/lib/structs/events/collections.cpp b/lib/structs/events/collections.cpp index 350cfe73bed1a6c3b948af68aaf679797fb1ab72..661dd38cfe29a739fca8ab08198fee5ae1169abf 100644 --- a/lib/structs/events/collections.cpp +++ b/lib/structs/events/collections.cpp @@ -79,6 +79,8 @@ MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::KeyVerificationM MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::RoomKey) MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::ForwardedRoomKey) MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::KeyRequest) +MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::SecretRequest) +MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::DeviceEvent, msgs::SecretSend) MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::Event, mtx::events::account_data::Tags) MTXCLIENT_INSTANTIATE_JSON_FUNCTIONS(events::Event, pushrules::GlobalRuleset) @@ -293,6 +295,8 @@ from_json(const json &obj, TimelineEvent &e) case events::EventType::Tag: // Not part of the timeline case events::EventType::Presence: // Not part of the timeline case events::EventType::PushRules: // Not part of the timeline + case events::EventType::SecretRequest: // Not part of the timeline + case events::EventType::SecretSend: // Not part of the timeline case events::EventType::NhekoHiddenEvents: case events::EventType::Unsupported: return; diff --git a/lib/structs/events/encrypted.cpp b/lib/structs/events/encrypted.cpp index ade1abd6cfc7b804d63a781b9ac5fd143777b204..432f365dfb927c0d0ed3f08c0d3bf3f77810caa0 100644 --- a/lib/structs/events/encrypted.cpp +++ b/lib/structs/events/encrypted.cpp @@ -435,6 +435,57 @@ to_json(json &obj, const KeyVerificationMac &event) obj["m.relates_to"] = event.relates_to.value(); } +void +from_json(const nlohmann::json &obj, SecretRequest &event) +{ + event.action = RequestAction::Unknown; + auto action = obj.value("action", ""); + if (action == "request") { + event.action = RequestAction::Request; + } else if (action == "request_cancellation") { + event.action = RequestAction::Cancellation; + } + + event.name = obj.value("name", ""); + + event.request_id = obj.value("request_id", ""); + event.requesting_device_id = obj.value("requesting_device_id", ""); +} + +void +to_json(nlohmann::json &obj, const SecretRequest &event) +{ + switch (event.action) { + case RequestAction::Request: + obj["action"] = "request"; + break; + case RequestAction::Cancellation: + obj["action"] = "request_cancellation"; + break; + default: + throw std::invalid_argument("Unknown secret request action type"); + } + + if (!event.name.empty()) + obj["name"] = event.name; + + obj["request_id"] = event.request_id; + obj["requesting_device_id"] = event.requesting_device_id; +} + +void +from_json(const nlohmann::json &obj, SecretSend &event) +{ + event.request_id = obj.value("request_id", ""); + event.secret = obj.value("secret", ""); +} + +void +to_json(nlohmann::json &obj, const SecretSend &event) +{ + obj["request_id"] = event.request_id; + obj["secret"] = event.secret; +} } // namespace msg } // namespace events } // namespace mtx diff --git a/lib/structs/responses/common.cpp b/lib/structs/responses/common.cpp index 23e9790d64451d231eef99e17ea2dda388584aa4..0381246a769dce00f03ddded0fbe1dd89afc6274 100644 --- a/lib/structs/responses/common.cpp +++ b/lib/structs/responses/common.cpp @@ -114,6 +114,8 @@ parse_room_account_data_events( case events::EventType::KeyVerificationAccept: case events::EventType::KeyVerificationKey: case events::EventType::KeyVerificationMac: + case events::EventType::SecretRequest: + case events::EventType::SecretSend: case events::EventType::Presence: case events::EventType::Reaction: case events::EventType::RoomAliases: @@ -554,6 +556,8 @@ parse_timeline_events(const json &events, case events::EventType::Tag: // Not part of the timeline or state case events::EventType::Presence: // Not part of the timeline or state case events::EventType::PushRules: // Not part of the timeline or state + case events::EventType::SecretRequest: // Not part of the timeline or state + case events::EventType::SecretSend: // Not part of the timeline or state case events::EventType::Unsupported: case events::EventType::NhekoHiddenEvents: continue; @@ -687,6 +691,22 @@ parse_device_events(const json &events, log_error(err, e); } + break; + case events::EventType::SecretSend: + try { + container.emplace_back(events::DeviceEvent<SecretSend>(e)); + } catch (json::exception &err) { + log_error(err, e); + } + + break; + case events::EventType::SecretRequest: + try { + container.emplace_back(events::DeviceEvent<SecretRequest>(e)); + } catch (json::exception &err) { + log_error(err, e); + } + break; default: continue; @@ -843,6 +863,8 @@ parse_state_events(const json &events, case events::EventType::KeyVerificationAccept: case events::EventType::KeyVerificationKey: case events::EventType::KeyVerificationMac: + case events::EventType::SecretRequest: + case events::EventType::SecretSend: case events::EventType::CallInvite: case events::EventType::CallCandidates: case events::EventType::CallAnswer: @@ -994,6 +1016,8 @@ parse_stripped_events(const json &events, case events::EventType::KeyVerificationAccept: case events::EventType::KeyVerificationKey: case events::EventType::KeyVerificationMac: + case events::EventType::SecretRequest: + case events::EventType::SecretSend: case events::EventType::CallInvite: case events::EventType::CallCandidates: case events::EventType::CallAnswer: diff --git a/tests/client_api.cpp b/tests/client_api.cpp index 1d4dab26ceee7464d6398b7540502eb8ef444876..3cb2a7508bd74685dc5f0a9195a1e9d38216871d 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -784,13 +784,14 @@ TEST(ClientAPI, Versions) mtx_client->versions([](const mtx::responses::Versions &res, RequestErr err) { check_error(err); - EXPECT_EQ(res.versions.size(), 6); + EXPECT_EQ(res.versions.size(), 7); EXPECT_EQ(res.versions.at(0), "r0.0.1"); EXPECT_EQ(res.versions.at(1), "r0.1.0"); EXPECT_EQ(res.versions.at(2), "r0.2.0"); EXPECT_EQ(res.versions.at(3), "r0.3.0"); EXPECT_EQ(res.versions.at(4), "r0.4.0"); EXPECT_EQ(res.versions.at(5), "r0.5.0"); + EXPECT_EQ(res.versions.at(6), "r0.6.0"); }); mtx_client->close(); diff --git a/tests/e2ee.cpp b/tests/e2ee.cpp index f2d08d2fb759c10030dae4ce2681008cae10c9b9..6f2cf68f0fc84ee76c5138f927ecdfc372aa6beb 100644 --- a/tests/e2ee.cpp +++ b/tests/e2ee.cpp @@ -903,6 +903,196 @@ TEST(Encryption, OlmRoomKeyEncryption) bob_http->close(); } +TEST(Encryption, ShareSecret) +{ + // Alice wants to use olm to send data to Bob. + auto alice_olm = std::make_shared<OlmClient>(); + auto alice_http = std::make_shared<Client>("localhost"); + alice_olm->create_new_account(); + alice_olm->generate_one_time_keys(10); + + auto bob_olm = std::make_shared<OlmClient>(); + auto bob_http = std::make_shared<Client>("localhost"); + bob_olm->create_new_account(); + bob_olm->generate_one_time_keys(10); + + alice_http->login("alice", "secret", &check_login); + bob_http->login("bob", "secret", &check_login); + + WAIT_UNTIL(!bob_http->access_token().empty() && !alice_http->access_token().empty()) + + bob_olm->set_user_id(bob_http->user_id().to_string()); + bob_olm->set_device_id(bob_http->device_id()); + alice_olm->set_user_id(alice_http->user_id().to_string()); + alice_olm->set_device_id(alice_http->device_id()); + + // Both users upload their identity & one time keys + atomic_int uploads(0); + auto upload_cb = [&uploads](const mtx::responses::UploadKeys &res, RequestErr err) { + check_error(err); + EXPECT_EQ(res.one_time_key_counts.size(), 1); + EXPECT_EQ(res.one_time_key_counts.at("signed_curve25519"), 10); + uploads += 1; + }; + + alice_http->upload_keys(alice_olm->create_upload_keys_request(), upload_cb); + bob_http->upload_keys(bob_olm->create_upload_keys_request(), upload_cb); + + WAIT_UNTIL(uploads == 2) + + atomic_bool request_finished(false); + std::string bob_ed25519, bob_curve25519, bob_otk; + + // Alice needs Bob's ed25519 device key. + mtx::requests::QueryKeys query; + query.device_keys[bob_http->user_id().to_string()] = {}; + alice_http->query_keys(query, + [&request_finished, &bob_ed25519, &bob_curve25519, bob = bob_http]( + const mtx::responses::QueryKeys &res, RequestErr err) { + check_error(err); + + const auto device_id = bob->device_id(); + const auto user_id = bob->user_id().to_string(); + const auto devices = res.device_keys.at(user_id); + + assert(devices.find(device_id) != devices.end()); + + bob_ed25519 = + devices.at(device_id).keys.at("ed25519:" + device_id); + bob_curve25519 = + devices.at(device_id).keys.at("curve25519:" + device_id); + + request_finished = true; + }); + + WAIT_UNTIL(request_finished); + + // Alice needs one of Bob's one time keys. + request_finished = false; + + mtx::requests::ClaimKeys claim_keys; + claim_keys.one_time_keys[bob_http->user_id().to_string()][bob_http->device_id()] = + SIGNED_CURVE25519; + + alice_http->claim_keys(claim_keys, + [&bob_otk, bob = bob_http, &request_finished]( + const mtx::responses::ClaimKeys &res, RequestErr err) { + check_error(err); + + const auto user_id = bob->user_id().to_string(); + const auto device_id = bob->device_id(); + + auto retrieved_devices = res.one_time_keys.at(user_id); + for (const auto &device : retrieved_devices) { + if (device.first == device_id) { + bob_otk = device.second.begin()->at("key"); + break; + } + } + + request_finished = true; + }); + + WAIT_UNTIL(request_finished); + + EXPECT_EQ(bob_ed25519, bob_olm->identity_keys().ed25519); + EXPECT_EQ(bob_curve25519, bob_olm->identity_keys().curve25519); + EXPECT_EQ(bob_otk, bob_olm->one_time_keys().curve25519.begin()->second); + + constexpr auto SECRET_TEXT = "Hello Bob!"; + constexpr auto REQUEST_ID = "askjfdgsdfgfdg"; + + // Alice create m.room.key request + mtx::events::msg::SecretRequest secretRequest{}; + secretRequest.request_id = REQUEST_ID; + secretRequest.name = "abcdefg"; + secretRequest.requesting_device_id = bob_http->device_id(); + secretRequest.action = RequestAction::Request; + + SyncOpts opts; + opts.timeout = 0; + + // Finally sends the olm encrypted message to Bob's device. + atomic_bool is_sent(false); + bob_http->send_to_device<SecretRequest>( + bob_http->generate_txn_id(), + {{alice_http->user_id(), {{alice_http->device_id(), secretRequest}}}}, + [&](RequestErr err) { + check_error(err); + + alice_http->sync(opts, [&](const mtx::responses::Sync &res, RequestErr err) { + check_error(err); + + mtx::events::DeviceEvent<mtx::events::msg::SecretSend> secretSend{}; + secretSend.content.secret = SECRET_TEXT; + secretSend.content.request_id = + std::get<mtx::events::DeviceEvent<mtx::events::msg::SecretRequest>>( + res.to_device.events.at(0)) + .content.request_id; + secretSend.type = mtx::events::EventType::SecretSend; + + json payload = secretSend; + + // Alice creates an outbound session. + auto out_session = + alice_olm->create_outbound_session(bob_curve25519, bob_otk); + auto device_msg = alice_olm->create_olm_encrypted_content( + out_session.get(), + payload, + UserId("@bob:localhost"), + bob_olm->identity_keys().ed25519, + bob_curve25519); + + std::map<mtx::identifiers::User, + std::map<std::string, mtx::events::msg::OlmEncrypted>> + body{{bob_http->user_id(), {{bob_http->device_id(), device_msg}}}}; + alice_http->send_to_device<OlmEncrypted>( + alice_http->generate_txn_id(), body, [&is_sent](RequestErr err) { + check_error(err); + is_sent = true; + }); + }); + }); + + WAIT_UNTIL(is_sent) + + bob_http->sync( + opts, + [bob = bob_olm, SECRET_TEXT, REQUEST_ID](const mtx::responses::Sync &res, + RequestErr err) { + check_error(err); + + EXPECT_EQ(res.to_device.events.size(), 1); + + auto olm_msg = + std::get<DeviceEvent<msgs::OlmEncrypted>>(res.to_device.events[0]).content; + auto cipher = olm_msg.ciphertext.begin(); + + EXPECT_EQ(cipher->first, bob->identity_keys().curve25519); + + const auto msg_body = cipher->second.body; + const auto msg_type = cipher->second.type; + + assert(msg_type == 0); + + auto inbound_session = bob->create_inbound_session(msg_body); + ASSERT_TRUE(matches_inbound_session_from( + inbound_session.get(), olm_msg.sender_key, msg_body)); + + auto output = bob->decrypt_message(inbound_session.get(), msg_type, msg_body); + + // Parsing the original plaintext json object. + auto ev = json::parse(std::string_view((char *)output.data(), output.size())) + .get<mtx::events::DeviceEvent<mtx::events::msg::SecretSend>>(); + + ASSERT_EQ(ev.content.secret, SECRET_TEXT); + ASSERT_EQ(ev.content.request_id, REQUEST_ID); + }); + + alice_http->close(); + bob_http->close(); +} + TEST(Encryption, PickleAccount) { auto alice = std::make_shared<OlmClient>(); diff --git a/tests/media_api.cpp b/tests/media_api.cpp index 3c76493c565e515d6ce827cea3c60f80ecba51c0..defd835234a1881bb09f5f83a11f3975aeefe072 100644 --- a/tests/media_api.cpp +++ b/tests/media_api.cpp @@ -50,24 +50,26 @@ TEST(MediaAPI, UploadTextFile) const auto text = "This is some random text"; - alice->upload(text, - "text/plain", - "doc.txt", - [alice, text](const mtx::responses::ContentURI &res, RequestErr err) { - validate_upload(res, err); - - alice->download(res.content_uri, - [text](const string &data, - const string &content_type, - const string &original_filename, - RequestErr err) { - ASSERT_FALSE(err); - EXPECT_EQ(data, text); - EXPECT_EQ(content_type, "text/plain"); - EXPECT_EQ(original_filename, - "doc.txt"); - }); - }); + alice->upload( + text, + "text/plain", + "doc.txt", + [alice, text](const mtx::responses::ContentURI &res, RequestErr err) { + validate_upload(res, err); + + alice->download( + res.content_uri, + [text](const string &data, + const string &content_type, + const string &original_filename, + RequestErr err) { + ASSERT_FALSE(err); + EXPECT_EQ(data, text); + EXPECT_EQ(content_type.substr(0, std::size("text/plain") - 1), + "text/plain"); + EXPECT_EQ(original_filename, "doc.txt"); + }); + }); }); alice->close();