From 80733faa896a52662b8399bbbc79ce04b33cfd46 Mon Sep 17 00:00:00 2001 From: Luca Saiu Date: Tue, 28 Mar 2023 16:36:14 +0200 Subject: [PATCH] add onion routing support --- src/pEp/_pEp/basic_api.cc | 19 ++++++++++++++ src/pEp/_pEp/basic_api.hh | 2 ++ src/pEp/_pEp/message.cc | 52 +++++++++++++++++++++++++++++++++++++++ src/pEp/_pEp/message.hh | 5 ++++ src/pEp/_pEp/pEpmodule.cc | 38 +++++++++++++++++++++++++++- 5 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/pEp/_pEp/basic_api.cc b/src/pEp/_pEp/basic_api.cc index 5afbc4e..4fa55cf 100644 --- a/src/pEp/_pEp/basic_api.cc +++ b/src/pEp/_pEp/basic_api.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include // local @@ -235,6 +236,24 @@ namespace pEp { PEP_STATUS status = PEP_STATUS_OK; status = ::send_ping(Adapter::session(), own_identity_c, other_identity_c); _throw_status(status); + + boost::python::list onion_identities(unsigned trusted_no, unsigned total_no) + { + ::identity_list *identities = NULL; + PEP_STATUS status = ::onion_identities(Adapter::session(), trusted_no, total_no, &identities); + _throw_status(status); + boost::python::list result; + for (::identity_list *il = identities; il && il->ident; il = il->next) { + ::pEp_identity *ident = ::identity_dup(il->ident); + if (!ident) { + free_identity_list(identities); + throw std::bad_alloc(); + } + result.append(Identity(ident)); + } + free_identity_list(identities); + return result; + } } // namespace PythonAdapter diff --git a/src/pEp/_pEp/basic_api.hh b/src/pEp/_pEp/basic_api.hh index 579c007..ca6cdef 100644 --- a/src/pEp/_pEp/basic_api.hh +++ b/src/pEp/_pEp/basic_api.hh @@ -36,6 +36,8 @@ namespace pEp { void set_comm_partner_key(Identity &ident, string fpr); void send_ping(Identity &own_identity, Identity &other_identity); + + boost::python::list onion_identities(unsigned trusted_no, unsigned total_no); } /* namespace PythonAdapter */ } /* namespace pEp */ diff --git a/src/pEp/_pEp/message.cc b/src/pEp/_pEp/message.cc index 2a83225..51e8dce 100644 --- a/src/pEp/_pEp/message.cc +++ b/src/pEp/_pEp/message.cc @@ -2,6 +2,7 @@ // see LICENSE.txt // System +#include ///////////////////////////////////////////////// #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include // local #include "message.hh" @@ -395,6 +397,56 @@ namespace pEp { return _color(outgoing_rating()); } + Message Message::onionize(boost::python::list relays) + { + return onionize(relays, boost::python::list(), (int) PEP_enc_PEP_message_v2, (int) PEP_encrypt_flag_default); + } + Message Message::onionize(boost::python::list relays, boost::python::list extra) + { + return onionize(relays, extra, (int) PEP_enc_PEP_message_v2, (int) PEP_encrypt_flag_default); + } + Message Message::onionize(boost::python::list relays, boost::python::list extra, int enc_format) + { + return onionize(relays, extra, enc_format, (int) PEP_encrypt_flag_default); + } + Message Message::onionize(boost::python::list relays, boost::python::list extra, int enc_format, int flags) + { + ::identity_list *identities_c = NULL; + PEP_STATUS status = PEP_STATUS_OK; + + // In case of any error, be it memory allocation or type conversion, + // free our temporary data before re-throwing to the caller. + ::pEp_identity *identity_c = NULL; + stringlist_t *extra_c = NULL; + try { + // Turn Python lists into C lists. + extra_c = to_stringlist(extra); + for (int i = len(relays) - 1; i >= 0; i--) { + Identity &identity = boost::python::extract(relays [i]); + ::identity_list *new_identities_c = identity_list_cons_copy(identity, identities_c); + if (new_identities_c == NULL) + throw std::bad_alloc(); + identities_c = new_identities_c; + } + + // Call the C function to do the actual work. + ::message *in_message_c = * this; + ::message *out_message_c = NULL; + status = ::onionize(Adapter::session(), in_message_c, extra_c, &out_message_c, (::PEP_enc_format) enc_format, (::PEP_encrypt_flags_t) flags, identities_c); + _throw_status(status); + + // Success. + free_stringlist(extra_c); + free_identity_list(identities_c); + return out_message_c; + } catch (const std::exception &e) { + free_identity(identity_c); + free_stringlist(extra_c); + free_identity_list(identities_c); + throw e; + } + } + Message Message::copy() { message *dup = message_dup(*this); diff --git a/src/pEp/_pEp/message.hh b/src/pEp/_pEp/message.hh index ed82103..75fe00d 100644 --- a/src/pEp/_pEp/message.hh +++ b/src/pEp/_pEp/message.hh @@ -315,6 +315,11 @@ namespace pEp { PEP_color outgoing_color(); + Message onionize(boost::python::list relays); + Message onionize(boost::python::list relays, boost::python::list extra); + Message onionize(boost::python::list relays, boost::python::list extra, int enc_format); + Message onionize(boost::python::list relays, boost::python::list extra, int enc_format, int flags); + Message deepcopy(dict &memo); Message copy(); diff --git a/src/pEp/_pEp/pEpmodule.cc b/src/pEp/_pEp/pEpmodule.cc index 77d3231..4be96e7 100644 --- a/src/pEp/_pEp/pEpmodule.cc +++ b/src/pEp/_pEp/pEpmodule.cc @@ -12,6 +12,7 @@ // Engine #include #include +#include #include #include #include @@ -406,7 +407,7 @@ namespace pEp { (void(Message::Blob::*)(string)) & Message::Blob::filename, "filename of object in Blob"); - ((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp; + //((PyTypeObject *)(void *)blob_class.ptr())->tp_as_buffer = &Message::Blob::bp; auto message_class = class_( "Message", @@ -593,6 +594,31 @@ namespace pEp { " keys a list of keys being used\n" " rating the rating of the message as integer\n" " flags flags set while decryption\n") + .def( + "onionize", + (Message(Message::*)(boost::python::list)) & + Message::onionize) + .def( + "onionize", + (Message(Message::*)(boost::python::list, boost::python::list)) & + Message::onionize) + .def( + "onionize", + (Message(Message::*)(boost::python::list, boost::python::list, int)) & + Message::onionize) + .def( + "onionize", + (Message(Message::*)(boost::python::list, boost::python::list, int, int)) & + Message::onionize, + "msg2 = msg1.onionize(relays, extra_keys = [], enc_format = 4, flags = 0)\n" + "\n" + "returns a copy of the message onionized with the given relay identities\n" + " relays a list of identities to use as relays\n" + " extra_keys a list of additional FPRs to encrypt the innermost message with" + " enc_format the encryption format, as in encrypt. Only\n" + " recent formats are supported.\n" + " flags flags, as in encrypt. Do not use onionisation flag\n" + " msg2 the resulting onionized message\n") .add_property( "outgoing_rating", &Message::outgoing_rating, @@ -712,6 +738,16 @@ namespace pEp { "own_identity the sender identity\n" "other_identity the recipient identity\n"); + def("onion_identities", + &onion_identities, + "onion_identities(trusted_no, total_no)\n" + "\n" + "Return a list of total_no known identities suitable to use as\n" + "onion-routing relays, of which at least trusted_no are trusted.\n" + "The returned identities are all distinct and in random order.\n" + "\n" + "identities = onion_identities(2, 5)\n"); + // message API enum_("rating")