/******************************************************************************* * libretroshare/src/retroshare: rsidentity.h * * * * libretroshare: retroshare core library * * * * Copyright (C) 2012 Robert Fernie * * Copyright (C) 2019-2021 Gioacchino Mazzurco * * Copyright (C) 2021 AsociaciĆ³n Civil Altermundi * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #pragma once #include #include #include #include #include "retroshare/rstokenservice.h" #include "retroshare/rsgxsifacehelper.h" #include "retroshare/rsreputations.h" #include "retroshare/rsids.h" #include "serialiser/rstlvimage.h" #include "retroshare/rsgxscommon.h" #include "serialiser/rsserializable.h" #include "serialiser/rstypeserializer.h" #include "util/rsdeprecate.h" class RsIdentity; /** * Pointer to global instance of RsIdentity service implementation * @jsonapi{development} */ extern RsIdentity* rsIdentity; // GroupFlags: Only one so far: // The deprecated flag overlaps the privacy flags for mGroupFlags. This is an error that should be fixed. For the sake of keeping some // backward compatibility, we need to make the change step by step. #define RSGXSID_GROUPFLAG_REALID_kept_for_compatibility 0x0001 #define RSGXSID_GROUPFLAG_REALID 0x0100 // THESE ARE FLAGS FOR INTERFACE. #define RSID_TYPE_MASK 0xff00 #define RSID_RELATION_MASK 0x00ff #define RSID_TYPE_REALID 0x0100 #define RSID_TYPE_PSEUDONYM 0x0200 #define RSID_RELATION_YOURSELF 0x0001 #define RSID_RELATION_FRIEND 0x0002 #define RSID_RELATION_FOF 0x0004 #define RSID_RELATION_OTHER 0x0008 #define RSID_RELATION_UNKNOWN 0x0010 /// @deprecated remove toghether with RsGxsIdGroup::mRecognTags #define RSRECOGN_MAX_TAGINFO 5 // Unicode symbols. NOT utf-8 bytes, because of multi byte characters #define RSID_MAXIMUM_NICKNAME_SIZE 30 #define RSID_MINIMUM_NICKNAME_SIZE 2 std::string rsIdTypeToString(uint32_t idtype); static const uint32_t RS_IDENTITY_FLAGS_IS_A_CONTACT = 0x0001; static const uint32_t RS_IDENTITY_FLAGS_PGP_LINKED = 0x0002; static const uint32_t RS_IDENTITY_FLAGS_PGP_KNOWN = 0x0004; static const uint32_t RS_IDENTITY_FLAGS_IS_OWN_ID = 0x0008; static const uint32_t RS_IDENTITY_FLAGS_IS_DEPRECATED= 0x0010; // used to denote keys with deprecated fingerprint format. struct GxsReputation : RsSerializable { GxsReputation(); bool updateIdScore(bool pgpLinked, bool pgpKnown); bool update(); /// checks ranges and calculates overall score. int32_t mOverallScore; int32_t mIdScore; /// PGP, Known, etc. int32_t mOwnOpinion; int32_t mPeerOpinion; /// @see RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override { RS_SERIAL_PROCESS(mOverallScore); RS_SERIAL_PROCESS(mIdScore); RS_SERIAL_PROCESS(mOwnOpinion); RS_SERIAL_PROCESS(mPeerOpinion); } ~GxsReputation() override; }; struct RsGxsIdGroup : RsSerializable { RsGxsIdGroup() : mLastUsageTS(0), mPgpKnown(false), mIsAContact(false) {} RsGroupMetaData mMeta; // In GroupMetaData. //std::string mNickname; (mGroupName) //std::string mKeyId; (mGroupId) //uint32_t mIdType; (mGroupFlags) // SHA(KeyId + Gpg Fingerprint) -> can only be IDed if GPG known. // The length of the input must be long enough to make brute force search implausible. // Easy to do 1e9 SHA-1 hash computations per second on a GPU. // We will need a minimum of 256 bits, ideally 1024 bits or 2048 bits. // Actually PgpIdHash is SHA1(.mMeta.mGroupId + PGPHandler->GpgFingerprint(ownId)) // ??? 160 bits. Sha1CheckSum mPgpIdHash; /** Need a signature as proof - otherwise anyone could add others Hashes. * This is a string, as the length is variable. * TODO: Thing like this should actually be a byte array (pointer+size), * using an std::string breaks the JSON serialization, as a workaround this * field is ignored by JSON serial operations */ std::string mPgpIdSign; /// Unused RS_DEPRECATED std::list mRecognTags; RsGxsImage mImage; /// Avatar rstime_t mLastUsageTS; bool mPgpLinked; bool mPgpKnown; bool mIsAContact; RsPgpId mPgpId; GxsReputation mReputation; /// @see RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override; ~RsGxsIdGroup() override; }; // DATA TYPE FOR EXTERNAL INTERFACE. struct RS_DEPRECATED RsRecognTag { RsRecognTag(uint16_t tc, uint16_t tt, bool v) : tag_class(tc), tag_type(tt), valid(v) {} uint16_t tag_class; uint16_t tag_type; bool valid; }; struct RS_DEPRECATED RsRecognTagDetails { RsRecognTagDetails() : valid_from(0), valid_to(0), tag_class(0), tag_type(0), is_valid(false), is_pending(false) {} rstime_t valid_from; rstime_t valid_to; uint16_t tag_class; uint16_t tag_type; std::string signer; bool is_valid; bool is_pending; }; struct RsIdentityParameters { RsIdentityParameters() : isPgpLinked(false) {} bool isPgpLinked; std::string nickname; RsGxsImage mImage; }; struct RsIdentityUsage : RsSerializable { enum UsageCode : uint8_t { UNKNOWN_USAGE = 0x00, /** These 2 are normally not normal GXS identities, but nothing prevents * it to happen either. */ GROUP_ADMIN_SIGNATURE_CREATION = 0x01, GROUP_ADMIN_SIGNATURE_VALIDATION = 0x02, /** Not typically used, since most services do not require group author * signatures */ GROUP_AUTHOR_SIGNATURE_CREATION = 0x03, GROUP_AUTHOR_SIGNATURE_VALIDATION = 0x04, /// most common use case. Messages are signed by authors in e.g. forums. MESSAGE_AUTHOR_SIGNATURE_CREATION = 0x05, MESSAGE_AUTHOR_SIGNATURE_VALIDATION = 0x06, /** Identities are stamped regularly by crawlign the set of messages for * all groups. That helps keepign the useful identities in hand. */ GROUP_AUTHOR_KEEP_ALIVE = 0x07, MESSAGE_AUTHOR_KEEP_ALIVE = 0x08, /** Chat lobby msgs are signed, so each time one comes, or a chat lobby * event comes, a signature verificaiton happens. */ CHAT_LOBBY_MSG_VALIDATION = 0x09, /// Global router message validation GLOBAL_ROUTER_SIGNATURE_CHECK = 0x0a, /// Global router message signature GLOBAL_ROUTER_SIGNATURE_CREATION = 0x0b, GXS_TUNNEL_DH_SIGNATURE_CHECK = 0x0c, GXS_TUNNEL_DH_SIGNATURE_CREATION = 0x0d, /// Identity received through GXS sync IDENTITY_NEW_FROM_GXS_SYNC = 0x0e, /// Group update on that identity data. Can be avatar, name, etc. IDENTITY_NEW_FROM_DISCOVERY = 0x0f, /// Explicit request to friend IDENTITY_NEW_FROM_EXPLICIT_REQUEST = 0x10, /// Any signature verified for that identity IDENTITY_GENERIC_SIGNATURE_CHECK = 0x11, /// Any signature made by that identity IDENTITY_GENERIC_SIGNATURE_CREATION = 0x12, IDENTITY_GENERIC_ENCRYPTION = 0x13, IDENTITY_GENERIC_DECRYPTION = 0x14, CIRCLE_MEMBERSHIP_CHECK = 0x15 } ; RsIdentityUsage( RsServiceType service, RsIdentityUsage::UsageCode code, const RsGxsGroupId& gid = RsGxsGroupId(), const RsGxsMessageId& message_id = RsGxsMessageId(), const RsGxsMessageId& parent_id = RsGxsMessageId(), const RsGxsMessageId& thread_id = RsGxsMessageId(), uint64_t additional_id=0, const std::string& comment = std::string() ); /// Id of the service using that identity, as understood by rsServiceControl RsServiceType mServiceId; /** Specific code to use. Will allow forming the correct translated message * in the GUI if necessary. */ UsageCode mUsageCode; /// Group ID using the identity RsGxsGroupId mGrpId; /// Message ID using the identity RsGxsMessageId mMsgId; /// Reference message ID. Useful for votes/comments RsGxsMessageId mParentId; /// Reference message ID. Useful for votes/comments RsGxsMessageId mThreadId; /// Some additional ID. Can be used for e.g. chat lobbies. uint64_t mAdditionalId; /// additional comment to be used mainly for debugging, but not GUI display std::string mComment; bool operator<(const RsIdentityUsage& u) const { return mHash < u.mHash; } RsFileHash mHash; /// @see RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override { RS_SERIAL_PROCESS(mServiceId); RS_SERIAL_PROCESS(mUsageCode); RS_SERIAL_PROCESS(mGrpId); RS_SERIAL_PROCESS(mMsgId); RS_SERIAL_PROCESS(mAdditionalId); RS_SERIAL_PROCESS(mComment); RS_SERIAL_PROCESS(mHash); } friend struct RsTypeSerializer; private: /** Accessible only to friend class RsTypeSerializer needed for * deserialization */ RsIdentityUsage(); }; enum class RsGxsIdentityEventCode: uint8_t { UNKNOWN = 0x00, NEW_IDENTITY = 0x01, DELETED_IDENTITY = 0x02, UPDATED_IDENTITY = 0x03, }; struct RsGxsIdentityEvent: public RsEvent { RsGxsIdentityEvent() : RsEvent(RsEventType::GXS_IDENTITY), mIdentityEventCode(RsGxsIdentityEventCode::UNKNOWN) {} RsGxsIdentityEventCode mIdentityEventCode; RsGxsGroupId mIdentityId; ///* @see RsEvent @see RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override { RsEvent::serial_process(j, ctx); RS_SERIAL_PROCESS(mIdentityEventCode); RS_SERIAL_PROCESS(mIdentityId); } ~RsGxsIdentityEvent() override = default; }; struct RsIdentityDetails : RsSerializable { RsIdentityDetails() : mFlags(0), mLastUsageTS(0) {} RsGxsId mId; std::string mNickname; uint32_t mFlags; RsPgpId mPgpId; /// @deprecated Recogn details. RS_DEPRECATED std::list mRecognTags; /** Cyril: Reputation details. At some point we might want to merge * information between the two into a single global score. Since the old * reputation system is not finished yet, I leave this in place. We should * decide what to do with it. */ RsReputationInfo mReputation; RsGxsImage mAvatar; rstime_t mPublishTS; rstime_t mLastUsageTS; std::map mUseCases; /// @see RsSerializable virtual void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override { RS_SERIAL_PROCESS(mId); RS_SERIAL_PROCESS(mNickname); RS_SERIAL_PROCESS(mFlags); RS_SERIAL_PROCESS(mPgpId); RS_SERIAL_PROCESS(mReputation); RS_SERIAL_PROCESS(mAvatar); RS_SERIAL_PROCESS(mPublishTS); RS_SERIAL_PROCESS(mLastUsageTS); RS_SERIAL_PROCESS(mUseCases); } ~RsIdentityDetails() override; }; /** The Main Interface Class for GXS people identities */ class RsIdentity: public RsGxsIfaceHelper { public: explicit RsIdentity(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {} /** * @brief Create a new identity * @jsonapi{development} * @param[out] id storage for the created identity Id * @param[in] name Name of the identity * @param[in] avatar Image associated to the identity * @param[in] pseudonimous true for unsigned identity, false otherwise * @param[in] pgpPassword password to unlock PGP to sign identity, * not implemented yet * @return false on error, true otherwise */ virtual bool createIdentity( RsGxsId& id, const std::string& name, const RsGxsImage& avatar = RsGxsImage(), bool pseudonimous = true, const std::string& pgpPassword = "" ) = 0; /** * @brief Locally delete given identity * @jsonapi{development} * @param[in] id Id of the identity * @return false on error, true otherwise */ virtual bool deleteIdentity(RsGxsId& id) = 0; /** * @brief Update identity data (name, avatar...) * @jsonapi{development} * @param[in] id Id of the identity * @param[in] name New name of the identity * @param[in] avatar New avatar for the identity * @param[in] pseudonimous Set to true to make the identity anonymous. If set to false, updating will require the profile passphrase. * @param[in] pgpPassword Profile passphrase, if non pseudonymous. * @return false on error, true otherwise */ virtual bool updateIdentity( const RsGxsId& id, const std::string& name, const RsGxsImage& avatar, bool pseudonimous, const std::string& pgpPassword) =0; /** * @brief Get identity details, from the cache * @jsonapi{development} * @param[in] id Id of the identity * @param[out] details Storage for the identity details * @return false on error, true otherwise */ virtual bool getIdDetails(const RsGxsId& id, RsIdentityDetails& details) = 0; /** * @brief Get last seen usage time of given identity * @jsonapi{development} * @param[in] id Id of the identity * @return timestamp of last seen usage */ virtual rstime_t getLastUsageTS(const RsGxsId& id) = 0; /** * @brief Get own signed ids * @jsonapi{development} * @param[out] ids storage for the ids * @return false on error, true otherwise */ virtual bool getOwnSignedIds(std::vector& ids) = 0; /** * @brief Get own pseudonimous (unsigned) ids * @jsonapi{development} * @param[out] ids storage for the ids * @return false on error, true otherwise */ virtual bool getOwnPseudonimousIds(std::vector& ids) = 0; /** * @brief Check if an id is known * @jsonapi{development} * @param[in] id Id to check * @return true if the id is known, false otherwise */ virtual bool isKnownId(const RsGxsId& id) = 0; /** * @brief Check if an id is own * @jsonapi{development} * @param[in] id Id to check * @return true if the id is own, false otherwise */ virtual bool isOwnId(const RsGxsId& id) = 0; /** * @brief Get identities summaries list. * @jsonapi{development} * @param[out] ids list where to store the identities * @return false if something failed, true otherwhise */ virtual bool getIdentitiesSummaries(std::list& ids) = 0; /** * @brief Get identities information (name, avatar...). * Blocking API. * @jsonapi{development} * @param[in] ids ids of the channels of which to get the informations * @param[out] idsInfo storage for the identities informations * @return false if something failed, true otherwhise */ virtual bool getIdentitiesInfo( const std::set& ids, std::vector& idsInfo ) = 0; /** * @brief Check if an identity is contact * @jsonapi{development} * @param[in] id Id of the identity * @return true if it is a conctact, false otherwise */ virtual bool isARegularContact(const RsGxsId& id) = 0; /** * @brief Set/unset identity as contact * @jsonapi{development} * @param[in] id Id of the identity * @param[in] isContact true to set, false to unset * @return false on error, true otherwise */ virtual bool setAsRegularContact(const RsGxsId& id, bool isContact) = 0; /** * @brief Toggle automatic flagging signed by friends identity as contact * @jsonapi{development} * @param[in] enabled true to enable, false to disable */ virtual void setAutoAddFriendIdsAsContact(bool enabled) = 0; /** * @brief Check if automatic signed by friend identity contact flagging is * enabled * @jsonapi{development} * @return true if enabled, false otherwise */ virtual bool autoAddFriendIdsAsContact() = 0; /** * @brief Get number of days after which delete a banned identities * @jsonapi{development} * @return number of days */ virtual uint32_t deleteBannedNodesThreshold() = 0; /** * @brief Set number of days after which delete a banned identities * @jsonapi{development} * @param[in] days number of days */ virtual void setDeleteBannedNodesThreshold(uint32_t days) = 0; /** * @brief request details of a not yet known identity to the network * @jsonapi{development} * @param[in] id id of the identity to request * @param[in] peers optional list of the peers to ask for the key, if empty * all online peers are asked. * @return false on error, true otherwise */ virtual bool requestIdentity( const RsGxsId& id, const std::vector& peers = std::vector() ) = 0; /// default base URL used for indentity links @see exportIdentityLink static const std::string DEFAULT_IDENTITY_BASE_URL; /// Link query field used to store indentity name @see exportIdentityLink static const std::string IDENTITY_URL_NAME_FIELD; /// Link query field used to store indentity id @see exportIdentityLink static const std::string IDENTITY_URL_ID_FIELD; /// Link query field used to store indentity data @see exportIdentityLink static const std::string IDENTITY_URL_DATA_FIELD; /** * @brief Get link to a identity * @jsonapi{development} * @param[out] link storage for the generated link * @param[in] id Id of the identity of which you want to generate a link * @param[in] includeGxsData if true include the identity GXS group data so * the receiver can make use of the identity even if she hasn't received it * through GXS yet * @param[in] baseUrl URL into which to sneak in the RetroShare link * radix, this is primarly useful to induce applications into making the * link clickable, or to disguise the RetroShare link into a * "normal" looking web link. If empty the GXS data link will be outputted * in plain base64 format. * @param[out] errMsg optional storage for error message, meaningful only in * case of failure * @return false if something failed, true otherwhise */ virtual bool exportIdentityLink( std::string& link, const RsGxsId& id, bool includeGxsData = true, const std::string& baseUrl = RsIdentity::DEFAULT_IDENTITY_BASE_URL, std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; /** * @brief Import identity from full link * @param[in] link identity link either in radix or link format * @param[out] id optional storage for parsed identity * @param[out] errMsg optional storage for error message, meaningful only in * case of failure * @return false if some error occurred, true otherwise */ virtual bool importIdentityLink( const std::string& link, RsGxsId& id = RS_DEFAULT_STORAGE_PARAM(RsGxsId), std::string& errMsg = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0; RS_DEPRECATED_FOR(exportIdentityLink) virtual bool getGroupSerializedData( const uint32_t& token, std::map& serialized_groups ) = 0; RS_DEPRECATED virtual bool parseRecognTag( const RsGxsId &id, const std::string& nickname, const std::string& tag, RsRecognTagDetails& details) = 0; RS_DEPRECATED virtual bool getRecognTagRequest( const RsGxsId& id, const std::string& comment, uint16_t tag_class, uint16_t tag_type, std::string& tag) = 0; RS_DEPRECATED virtual uint32_t nbRegularContacts() =0; RS_DEPRECATED_FOR(exportIdentityLink) virtual bool serialiseIdentityToMemory( const RsGxsId& id, std::string& radix_string ) = 0; RS_DEPRECATED_FOR(importIdentityLink) virtual bool deserialiseIdentityFromMemory( const std::string& radix_string, RsGxsId* id = nullptr ) = 0; /// Fills up list of all own ids. Returns false if ids are not yet loaded. RS_DEPRECATED_FOR("getOwnSignedIds getOwnPseudonimousIds") virtual bool getOwnIds( std::list &ownIds, bool only_signed_ids = false ) = 0; RS_DEPRECATED virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) = 0; RS_DEPRECATED_FOR(RsReputations) virtual bool submitOpinion(uint32_t& token, const RsGxsId &id, bool absOpinion, int score) = 0; RS_DEPRECATED virtual bool deleteIdentity(uint32_t& token, RsGxsIdGroup &group) = 0; RS_DEPRECATED_FOR("getIdentitiesSummaries getIdentitiesInfo") virtual bool getGroupData( const uint32_t& token, std::vector& groups) = 0; virtual ~RsIdentity(); };