From fc588614478762128b469d85f942d167c5bcbf43 Mon Sep 17 00:00:00 2001 From: drbob Date: Sun, 20 Oct 2013 09:43:30 +0000 Subject: [PATCH] Added RecognTags. - items are described in serialiser. - util functions in util/rsrecogn.cc are used to manipulate it. - these are attached to GxsIds, with new interface fns. - Associated Signing Code is in a separate program. Other Tweaks. - Added RsMemCache::erase() - Added RsTlvStringSetRef - Fix for rsturtleitem (already added to trunk). - Formatting and debugging. Status: There is a bug in RsGenExchange::updateGroup which prevents full testing, The basic generation, parsing and validation functions have been tested and are ok. The processing as part of p3IdService still needs to be fully debugged. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs_finale@6854 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/libretroshare.pro | 6 +- .../src/retroshare/rsgxsifacetypes.h | 2 +- libretroshare/src/retroshare/rsidentity.h | 45 + libretroshare/src/serialiser/rsgxsiditems.cc | 20 + libretroshare/src/serialiser/rsgxsitems.cc | 3 +- .../src/serialiser/rsgxsrecognitems.cc | 600 ++++++++++++ .../src/serialiser/rsgxsrecognitems.h | 152 +++ libretroshare/src/serialiser/rsserviceids.h | 2 + libretroshare/src/serialiser/rstlvbase.h | 1 + libretroshare/src/serialiser/rstlvtypes.cc | 159 +++ libretroshare/src/serialiser/rstlvtypes.h | 16 + libretroshare/src/services/p3gxsforums.cc | 2 +- libretroshare/src/services/p3idservice.cc | 921 ++++++++++++++++-- libretroshare/src/services/p3idservice.h | 69 +- libretroshare/src/services/p3posted.cc | 1 - libretroshare/src/turtle/rsturtleitem.cc | 4 +- libretroshare/src/util/rsmemcache.h | 42 + libretroshare/src/util/rsrecogn.cc | 640 ++++++++++++ libretroshare/src/util/rsrecogn.h | 61 ++ 19 files changed, 2645 insertions(+), 101 deletions(-) create mode 100644 libretroshare/src/serialiser/rsgxsrecognitems.cc create mode 100644 libretroshare/src/serialiser/rsgxsrecognitems.h create mode 100644 libretroshare/src/util/rsrecogn.cc create mode 100644 libretroshare/src/util/rsrecogn.h diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index de0cfed2a..42fc6e8f8 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -7,7 +7,7 @@ CONFIG += test_voip #GXS Stuff. # This should be disabled for releases until further notice. -#CONFIG += gxs debug +CONFIG += gxs debug # Beware: All data of the stripped services are lost DEFINES *= PQI_DISABLE_TUNNEL @@ -387,6 +387,7 @@ HEADERS += serialiser/rsbaseitems.h \ serialiser/rstlvbanlist.h \ serialiser/rsbanlistitems.h \ serialiser/rsbwctrlitems.h \ + serialiser/rsgxsrecognitems.h \ serialiser/rstunnelitems.h HEADERS += services/p3channels.h \ @@ -430,6 +431,7 @@ HEADERS += util/folderiterator.h \ util/pugiconfig.h \ util/rsmemcache.h \ util/rstickevent.h \ + util/rsrecogn.h \ SOURCES += dbase/cachestrapper.cc \ dbase/fimonitor.cc \ @@ -529,6 +531,7 @@ SOURCES += serialiser/rsbaseitems.cc \ serialiser/rstlvbanlist.cc \ serialiser/rsbanlistitems.cc \ serialiser/rsbwctrlitems.cc \ + serialiser/rsgxsrecognitems.cc \ serialiser/rstunnelitems.cc SOURCES += services/p3channels.cc \ @@ -571,6 +574,7 @@ SOURCES += util/folderiterator.cc \ util/rsaes.cc \ util/rsrandom.cc \ util/rstickevent.cc \ + util/rsrecogn.cc \ upnp_miniupnpc { diff --git a/libretroshare/src/retroshare/rsgxsifacetypes.h b/libretroshare/src/retroshare/rsgxsifacetypes.h index f2181e363..830df9f52 100644 --- a/libretroshare/src/retroshare/rsgxsifacetypes.h +++ b/libretroshare/src/retroshare/rsgxsifacetypes.h @@ -47,7 +47,7 @@ public: mGroupStatus = 0; mCircleType = 0; - //mPublishTs = 0; + mPublishTs = 0; } void operator =(const RsGxsGrpMetaData& rGxsMeta); diff --git a/libretroshare/src/retroshare/rsidentity.h b/libretroshare/src/retroshare/rsidentity.h index 4b78f0a38..a1891e6ac 100644 --- a/libretroshare/src/retroshare/rsidentity.h +++ b/libretroshare/src/retroshare/rsidentity.h @@ -55,6 +55,8 @@ extern RsIdentity *rsIdentity; #define RSID_RELATION_OTHER 0x0008 #define RSID_RELATION_UNKNOWN 0x0010 +#define RSRECOGN_MAX_TAGINFO 5 + std::string rsIdTypeToString(uint32_t idtype); class RsGxsIdGroup @@ -82,6 +84,9 @@ class RsGxsIdGroup std::string mPgpIdHash; std::string mPgpIdSign; // Need a signature as proof - otherwise anyone could add others Hashes. + // Recognition Strings. MAX# defined above. + std::list mRecognTags; + // Not Serialised - for GUI's benefit. bool mPgpKnown; std::string mPgpId; @@ -163,6 +168,36 @@ class RsIdOpinion typedef std::string RsGxsId; // TMP. => +class RsRecognTag +{ + public: + RsRecognTag(uint16_t tc, uint16_t tt, bool v) + :tag_class(tc), tag_type(tt), valid(v) { return; } + uint16_t tag_class; + uint16_t tag_type; + bool valid; +}; + + +class RsRecognTagDetails +{ + public: + RsRecognTagDetails() + :valid_from(0), valid_to(0), tag_class(0), tag_type(0), + is_valid(false), is_pending(false) { return; } + + time_t valid_from; + time_t valid_to; + uint16_t tag_class; + uint16_t tag_type; + + std::string signer; + + bool is_valid; + bool is_pending; +}; + + class RsIdentityDetails { public: @@ -181,6 +216,9 @@ class RsIdentityDetails bool mPgpKnown; std::string mPgpId; + // Recogn details. + std::list mRecognTags; + // reputation details. double mOpinion; double mReputation; @@ -230,6 +268,13 @@ virtual bool getOwnIds(std::list &ownIds) = 0; virtual bool submitOpinion(uint32_t& token, RsIdOpinion &opinion) = 0; virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms) = 0; +virtual bool updateIdentity(uint32_t& token, RsGxsIdGroup &group) = 0; + +virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname, + const std::string &tag, RsRecognTagDetails &details) = 0; +virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, + uint16_t tag_class, uint16_t tag_type, std::string &tag) = 0; + // Specific RsIdentity Functions.... /* Specific Service Data */ /* We expose these initially for testing / GUI purposes. diff --git a/libretroshare/src/serialiser/rsgxsiditems.cc b/libretroshare/src/serialiser/rsgxsiditems.cc index e22055b7a..7853afeaf 100644 --- a/libretroshare/src/serialiser/rsgxsiditems.cc +++ b/libretroshare/src/serialiser/rsgxsiditems.cc @@ -122,20 +122,30 @@ void RsGxsIdGroupItem::clear() group.mPgpIdHash.clear(); group.mPgpIdSign.clear(); + group.mRecognTags.clear(); + group.mPgpKnown = false; group.mPgpId.clear(); } + std::ostream& RsGxsIdGroupItem::print(std::ostream& out, uint16_t indent) { printRsItemBase(out, "RsGxsIdGroupItem", indent); uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); + out << "MetaData: " << meta << std::endl; printIndent(out, int_Indent); out << "PgpIdHash: " << group.mPgpIdHash << std::endl; printIndent(out, int_Indent); out << "PgpIdSign: " << group.mPgpIdSign << std::endl; + printIndent(out, int_Indent); + out << "RecognTags:" << std::endl; + + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, group.mRecognTags); + set.print(out, int_Indent + 2); printRsItemEnd(out ,"RsGxsIdGroupItem", indent); return out; @@ -151,6 +161,9 @@ uint32_t RsGxsIdSerialiser::sizeGxsIdGroupItem(RsGxsIdGroupItem *item) s += GetTlvStringSize(group.mPgpIdHash); s += GetTlvStringSize(group.mPgpIdSign); + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->group.mRecognTags); + s += set.TlvSize(); + return s; } @@ -181,6 +194,9 @@ bool RsGxsIdSerialiser::serialiseGxsIdGroupItem(RsGxsIdGroupItem *item, void *da /* GxsIdGroupItem */ ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdHash); ok &= SetTlvString(data, tlvsize, &offset, 1, item->group.mPgpIdSign); + + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->group.mRecognTags); + ok &= set.SetTlv(data, tlvsize, &offset); if(offset != tlvsize) { @@ -238,6 +254,10 @@ RsGxsIdGroupItem* RsGxsIdSerialiser::deserialiseGxsIdGroupItem(void *data, uint3 ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdHash); ok &= GetTlvString(data, rssize, &offset, 1, item->group.mPgpIdSign); + + RsTlvStringSetRef set(TLV_TYPE_RECOGNSET, item->group.mRecognTags); + ok &= set.GetTlv(data, rssize, &offset); + if (offset != rssize) { diff --git a/libretroshare/src/serialiser/rsgxsitems.cc b/libretroshare/src/serialiser/rsgxsitems.cc index 6cc57e90c..e1acdf0fd 100644 --- a/libretroshare/src/serialiser/rsgxsitems.cc +++ b/libretroshare/src/serialiser/rsgxsitems.cc @@ -52,7 +52,8 @@ std::ostream &operator<<(std::ostream &out, const RsGroupMetaData &meta) { - out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName << " ]"; + out << "[ GroupId: " << meta.mGroupId << " Name: " << meta.mGroupName; + out << " PublishTs: " << meta.mPublishTs << " ]"; return out; } diff --git a/libretroshare/src/serialiser/rsgxsrecognitems.cc b/libretroshare/src/serialiser/rsgxsrecognitems.cc new file mode 100644 index 000000000..89b4576aa --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsrecognitems.cc @@ -0,0 +1,600 @@ +/* + * libretroshare/src/serialiser: rsgxsrecogitems.cc + * + * RetroShare Serialiser. + * + * Copyright 2013-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "serialiser/rsbaseserial.h" +#include "serialiser/rsgxsrecognitems.h" + +/*** +#define RSSERIAL_DEBUG 1 +***/ + +#include + +/*************************************************************************/ + +RsGxsRecognReqItem::~RsGxsRecognReqItem() +{ + return; +} + +void RsGxsRecognReqItem::clear() +{ + issued_at = 0; + period = 0; + tag_class = 0; + tag_type = 0; + + identity.clear(); + nickname.clear(); + comment.clear(); + + sign.TlvClear(); + +} + +std::ostream &RsGxsRecognReqItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsRecognReqItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "issued_at: " << issued_at << std::endl; + + printIndent(out, int_Indent); + out << "period: " << period << std::endl; + + printIndent(out, int_Indent); + out << "tag_class: " << tag_class << std::endl; + + printIndent(out, int_Indent); + out << "tag_type: " << tag_type << std::endl; + + printIndent(out, int_Indent); + out << "identity: " << identity << std::endl; + + printIndent(out, int_Indent); + out << "nickname: " << nickname << std::endl; + + printIndent(out, int_Indent); + out << "comment: " << comment << std::endl; + + printIndent(out, int_Indent); + out << "signature: " << std::endl; + sign.print(out, int_Indent + 2); + + printRsItemEnd(out, "RsGxsRecognReqItem", indent); + return out; +} + + +uint32_t RsGxsRecognSerialiser::sizeReq(RsGxsRecognReqItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; // issued_at; + s += 4; // period; + s += 2; // tag_class; + s += 2; // tag_type; + s += GetTlvStringSize(item->identity); + s += GetTlvStringSize(item->nickname); + s += GetTlvStringSize(item->comment); + s += item->sign.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsGxsRecognSerialiser::serialiseReq(RsGxsRecognReqItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseReq() Header: " << ok << std::endl; + std::cerr << "RsGxsRecognSerialiser::serialiseReq() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, item->issued_at); + ok &= setRawUInt32(data, tlvsize, &offset, item->period); + ok &= setRawUInt16(data, tlvsize, &offset, item->tag_class); + ok &= setRawUInt16(data, tlvsize, &offset, item->tag_type); + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->identity); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->nickname); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->comment); + ok &= item->sign.SetTlv(data, tlvsize, &offset); + + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseReq() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsGxsRecognReqItem *RsGxsRecognSerialiser::deserialiseReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t tlvsize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_GXS_RECOGN != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RECOGN_REQ != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < tlvsize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = tlvsize; + + bool ok = true; + + /* ready to load */ + RsGxsRecognReqItem *item = new RsGxsRecognReqItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= getRawUInt32(data, tlvsize, &offset, &(item->issued_at)); + ok &= getRawUInt32(data, tlvsize, &offset, &(item->period)); + ok &= getRawUInt16(data, tlvsize, &offset, &(item->tag_class)); + ok &= getRawUInt16(data, tlvsize, &offset, &(item->tag_type)); + + ok &= GetTlvString(data, tlvsize, &offset, 1, item->identity); + ok &= GetTlvString(data, tlvsize, &offset, 1, item->nickname); + ok &= GetTlvString(data, tlvsize, &offset, 1, item->comment); + ok &= item->sign.GetTlv(data, tlvsize, &offset); + + + if (offset != tlvsize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +RsGxsRecognTagItem::~RsGxsRecognTagItem() +{ + return; +} + +void RsGxsRecognTagItem::clear() +{ + valid_from = 0; + valid_to = 0; + + tag_class = 0; + tag_type = 0; + + identity.clear(); + nickname.clear(); + + sign.TlvClear(); +} + +std::ostream &RsGxsRecognTagItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsRecognTagItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "valid_from: " << valid_from << std::endl; + + printIndent(out, int_Indent); + out << "valid_to: " << valid_to << std::endl; + + printIndent(out, int_Indent); + out << "tag_class: " << tag_class << std::endl; + + printIndent(out, int_Indent); + out << "tag_type: " << tag_type << std::endl; + + printIndent(out, int_Indent); + out << "identity: " << identity << std::endl; + + printIndent(out, int_Indent); + out << "nickname: " << nickname << std::endl; + + printIndent(out, int_Indent); + out << "signature: " << std::endl; + sign.print(out, int_Indent + 2); + + printRsItemEnd(out, "RsGxsRecognTagItem", indent); + return out; +} + + +uint32_t RsGxsRecognSerialiser::sizeTag(RsGxsRecognTagItem *item) +{ + uint32_t s = 8; /* header */ + s += 4; // valid_from; + s += 4; // valid_to; + s += 2; // tag_class; + s += 2; // tag_type; + + s += GetTlvStringSize(item->identity); + s += GetTlvStringSize(item->nickname); + + s += item->sign.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsGxsRecognSerialiser::serialiseTag(RsGxsRecognTagItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeTag(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseTag() Header: " << ok << std::endl; + std::cerr << "RsGxsRecognSerialiser::serialiseTag() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt32(data, tlvsize, &offset, item->valid_from); + ok &= setRawUInt32(data, tlvsize, &offset, item->valid_to); + + ok &= setRawUInt16(data, tlvsize, &offset, item->tag_class); + ok &= setRawUInt16(data, tlvsize, &offset, item->tag_type); + + ok &= SetTlvString(data, tlvsize, &offset, 1, item->identity); + ok &= SetTlvString(data, tlvsize, &offset, 1, item->nickname); + ok &= item->sign.SetTlv(data, tlvsize, &offset); + + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseTag() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsGxsRecognTagItem *RsGxsRecognSerialiser::deserialiseTag(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t tlvsize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_GXS_RECOGN != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RECOGN_TAG != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < tlvsize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = tlvsize; + + bool ok = true; + + /* ready to load */ + RsGxsRecognTagItem *item = new RsGxsRecognTagItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= getRawUInt32(data, tlvsize, &offset, &(item->valid_from)); + ok &= getRawUInt32(data, tlvsize, &offset, &(item->valid_to)); + + ok &= getRawUInt16(data, tlvsize, &offset, &(item->tag_class)); + ok &= getRawUInt16(data, tlvsize, &offset, &(item->tag_type)); + + ok &= GetTlvString(data, tlvsize, &offset, 1, item->identity); + ok &= GetTlvString(data, tlvsize, &offset, 1, item->nickname); + ok &= item->sign.GetTlv(data, tlvsize, &offset); + + + if (offset != tlvsize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +RsGxsRecognSignerItem::~RsGxsRecognSignerItem() +{ + return; +} + +void RsGxsRecognSignerItem::clear() +{ + signing_classes.TlvClear(); + key.TlvClear(); + sign.TlvClear(); +} + +std::ostream &RsGxsRecognSignerItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsGxsRecognSignerItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "signing_classes: " << std::endl; + signing_classes.print(out, int_Indent + 2); + + printIndent(out, int_Indent); + out << "key: " << std::endl; + key.print(out, int_Indent + 2); + + printIndent(out, int_Indent); + out << "signature: " << std::endl; + sign.print(out, int_Indent + 2); + + + printRsItemEnd(out, "RsGxsRecognSignerItem", indent); + return out; +} + + + + +uint32_t RsGxsRecognSerialiser::sizeSigner(RsGxsRecognSignerItem *item) +{ + uint32_t s = 8; /* header */ + s += item->signing_classes.TlvSize(); + s += item->key.TlvSize(); + s += item->sign.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsGxsRecognSerialiser::serialiseSigner(RsGxsRecognSignerItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeSigner(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseSigner() Header: " << ok << std::endl; + std::cerr << "RsGxsRecognSerialiser::serialiseSigner() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->signing_classes.SetTlv(data, tlvsize, &offset); + ok &= item->key.SetTlv(data, tlvsize, &offset); + ok &= item->sign.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsGxsRecognSerialiser::serialiseSigner() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsGxsRecognSignerItem *RsGxsRecognSerialiser::deserialiseSigner(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t tlvsize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_GXS_RECOGN != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_RECOGN_SIGNER != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < tlvsize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = tlvsize; + + bool ok = true; + + /* ready to load */ + RsGxsRecognSignerItem *item = new RsGxsRecognSignerItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->signing_classes.GetTlv(data, tlvsize, &offset); + ok &= item->key.GetTlv(data, tlvsize, &offset); + ok &= item->sign.GetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + + +/*************************************************************************/ + +uint32_t RsGxsRecognSerialiser::size(RsItem *i) +{ + RsGxsRecognReqItem *rqi; + RsGxsRecognTagItem *rti; + RsGxsRecognSignerItem *rsi; + + if (NULL != (rqi = dynamic_cast(i))) + { + return sizeReq(rqi); + } + if (NULL != (rti = dynamic_cast(i))) + { + return sizeTag(rti); + } + if (NULL != (rsi = dynamic_cast(i))) + { + return sizeSigner(rsi); + } + return 0; +} + +bool RsGxsRecognSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsGxsRecognReqItem *rri; + RsGxsRecognTagItem *rti; + RsGxsRecognSignerItem *rsi; + + if (NULL != (rri = dynamic_cast(i))) + { + return serialiseReq(rri, data, pktsize); + } + if (NULL != (rti = dynamic_cast(i))) + { + return serialiseTag(rti, data, pktsize); + } + if (NULL != (rsi = dynamic_cast(i))) + { + return serialiseSigner(rsi, data, pktsize); + } + return false; +} + +RsItem *RsGxsRecognSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_GXS_RECOGN != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_RECOGN_REQ: + return deserialiseReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_RECOGN_TAG: + return deserialiseTag(data, pktsize); + break; + case RS_PKT_SUBTYPE_RECOGN_SIGNER: + return deserialiseSigner(data, pktsize); + break; + default: + return NULL; + break; + } +} + +/*************************************************************************/ + + + diff --git a/libretroshare/src/serialiser/rsgxsrecognitems.h b/libretroshare/src/serialiser/rsgxsrecognitems.h new file mode 100644 index 000000000..fdbc9cfc2 --- /dev/null +++ b/libretroshare/src/serialiser/rsgxsrecognitems.h @@ -0,0 +1,152 @@ +#ifndef RS_GXS_RECOG_ITEMS_H +#define RS_GXS_RECOG_ITEMS_H + +/* + * libretroshare/src/serialiser: rsgxsrecogitems.h + * + * RetroShare Serialiser. + * + * Copyright 2013-2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include + +#include "serialiser/rsserviceids.h" +#include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvkeys.h" + +/**************************************************************************/ + +#define RS_PKT_SUBTYPE_RECOGN_REQ 0x01 +#define RS_PKT_SUBTYPE_RECOGN_TAG 0x02 +#define RS_PKT_SUBTYPE_RECOGN_SIGNER 0x03 + + +class RsGxsRecognReqItem: public RsItem +{ + public: + RsGxsRecognReqItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, + RS_PKT_SUBTYPE_RECOGN_REQ) + { + setPriorityLevel(QOS_PRIORITY_DEFAULT); + return; + } +virtual ~RsGxsRecognReqItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + + uint32_t issued_at; + uint32_t period; + uint16_t tag_class; + uint16_t tag_type; + + std::string identity; + std::string nickname; + std::string comment; + + RsTlvKeySignature sign; +}; + + +class RsGxsRecognTagItem: public RsItem +{ + public: + RsGxsRecognTagItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, + RS_PKT_SUBTYPE_RECOGN_TAG) + { + setPriorityLevel(QOS_PRIORITY_DEFAULT); + return; + } +virtual ~RsGxsRecognTagItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + uint32_t valid_from; + uint32_t valid_to; + uint16_t tag_class; + uint16_t tag_type; + + std::string identity; + std::string nickname; + + RsTlvKeySignature sign; +}; + + +class RsGxsRecognSignerItem: public RsItem +{ + public: + RsGxsRecognSignerItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN, + RS_PKT_SUBTYPE_RECOGN_SIGNER) + { + setPriorityLevel(QOS_PRIORITY_DEFAULT); + return; + } +virtual ~RsGxsRecognSignerItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvServiceIdSet signing_classes; + RsTlvSecurityKey key; // has from->to, and flags. + RsTlvKeySignature sign; +}; + + +class RsGxsRecognSerialiser: public RsSerialType +{ + public: + RsGxsRecognSerialiser() + :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_RECOGN) + { return; } +virtual ~RsGxsRecognSerialiser() + { return; } + + +virtual uint32_t size(RsItem *); +virtual bool serialise (RsItem *item, void *data, uint32_t *size); +virtual RsItem * deserialise(void *data, uint32_t *size); + + private: + +virtual uint32_t sizeReq(RsGxsRecognReqItem *); +virtual bool serialiseReq(RsGxsRecognReqItem *item, void *data, uint32_t *size); +virtual RsGxsRecognReqItem *deserialiseReq(void *data, uint32_t *size); + +virtual uint32_t sizeTag(RsGxsRecognTagItem *); +virtual bool serialiseTag(RsGxsRecognTagItem *item, void *data, uint32_t *size); +virtual RsGxsRecognTagItem *deserialiseTag(void *data, uint32_t *size); + +virtual uint32_t sizeSigner(RsGxsRecognSignerItem *); +virtual bool serialiseSigner(RsGxsRecognSignerItem *item, void *data, uint32_t *size); +virtual RsGxsRecognSignerItem *deserialiseSigner(void *data, uint32_t *size); + +}; + +/**************************************************************************/ + +#endif /* RS_GXS_RECOGN_ITEMS_H */ + + diff --git a/libretroshare/src/serialiser/rsserviceids.h b/libretroshare/src/serialiser/rsserviceids.h index 8095ed575..efa22dc32 100644 --- a/libretroshare/src/serialiser/rsserviceids.h +++ b/libretroshare/src/serialiser/rsserviceids.h @@ -149,6 +149,8 @@ const uint16_t RS_SERVICE_GXSV3_TYPE_POSTED = 0xf326; const uint16_t RS_SERVICE_GXSV3_TYPE_CHANNELS = 0xf327; const uint16_t RS_SERVICE_GXSV3_TYPE_GXSCIRCLE = 0xf328; +const uint16_t RS_SERVICE_TYPE_GXS_RECOGN = 0xf331; + /***************** IDS ALLOCATED FOR PLUGINS ******************/ const uint16_t RS_SERVICE_TYPE_PLUGIN_ARADO_TEST_ID1 = 0xf401; diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h index 70698df64..613545440 100644 --- a/libretroshare/src/serialiser/rstlvbase.h +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -201,6 +201,7 @@ const uint16_t TLV_TYPE_WKEYVALUESET = 0x1013; const uint16_t TLV_TYPE_STRINGSET = 0x1020; /* dummy non-existant */ const uint16_t TLV_TYPE_PEERSET = 0x1021; const uint16_t TLV_TYPE_HASHSET = 0x1022; +const uint16_t TLV_TYPE_RECOGNSET = 0x1023; const uint16_t TLV_TYPE_SERVICESET = 0x1030; const uint16_t TLV_TYPE_SECURITYKEY = 0x1040; diff --git a/libretroshare/src/serialiser/rstlvtypes.cc b/libretroshare/src/serialiser/rstlvtypes.cc index 6a2fc0579..1c1db3cd8 100644 --- a/libretroshare/src/serialiser/rstlvtypes.cc +++ b/libretroshare/src/serialiser/rstlvtypes.cc @@ -428,6 +428,165 @@ std::ostream &RsTlvStringSet::printHex(std::ostream &out, uint16_t indent) } +/************************************* String Set Ref ************************************/ +/* This is exactly the same as StringSet, but it uses an alternative list. + */ +RsTlvStringSetRef::RsTlvStringSetRef(uint16_t type, std::list &refids) + :mType(type), ids(refids) +{ +} + +void RsTlvStringSetRef::TlvClear() +{ + ids.clear(); + +} + +uint32_t RsTlvStringSetRef::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + /* determine the total size of ids strings in list */ + + std::list::iterator it; + + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (it->length() > 0) + s += GetTlvStringSize(*it); + } + + return s; +} + + +bool RsTlvStringSetRef::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + + /* start at data[offset] */ + ok &= SetTlvBase(data, tlvend, offset, mType , tlvsize); + + /* determine the total size of ids strings in list */ + + std::list::iterator it; + + for(it = ids.begin(); it != ids.end() ; ++it) + { + if (it->length() > 0) + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, *it); + } + + return ok; + +} + + +bool RsTlvStringSetRef::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != mType) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + + +/* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + if (tlvsubtype == TLV_TYPE_STR_GENID) + { + std::string newIds; + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, newIds); + if(ok) + { + ids.push_back(newIds); + + } + } + else + { + /* Step past unknown TLV TYPE */ + ok &= SkipUnknownTlv(data, tlvend, offset); + } + + if (!ok) + { + break; + } + } + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvPeerIdSetRef::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +/// print to screen RsTlvStringSet contents +std::ostream &RsTlvStringSetRef::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvStringSetRef", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "type:" << mType; + out << std::endl; + + std::list::iterator it; + for(it = ids.begin(); it != ids.end() ; ++it) + { + printIndent(out, int_Indent); + out << "id:" << *it; + out << std::endl; + } + + printEnd(out, "RsTlvStringSetRef", indent); + return out; + +} + /************************************* Service Id Set ************************************/ void RsTlvServiceIdSet::TlvClear() diff --git a/libretroshare/src/serialiser/rstlvtypes.h b/libretroshare/src/serialiser/rstlvtypes.h index 4148faa62..9bae52f89 100644 --- a/libretroshare/src/serialiser/rstlvtypes.h +++ b/libretroshare/src/serialiser/rstlvtypes.h @@ -137,6 +137,22 @@ virtual std::ostream &print(std::ostream &out, uint16_t indent); }; +class RsTlvStringSetRef: public RsTlvItem +{ + public: + RsTlvStringSetRef(uint16_t type, std::list &refids); +virtual ~RsTlvStringSetRef() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint16_t mType; + std::list &ids; /* Mandatory */ +}; + + /**** MORE TLV ***** * * File Items/Data. diff --git a/libretroshare/src/services/p3gxsforums.cc b/libretroshare/src/services/p3gxsforums.cc index 7b7766bd2..bdc8472e0 100644 --- a/libretroshare/src/services/p3gxsforums.cc +++ b/libretroshare/src/services/p3gxsforums.cc @@ -217,7 +217,7 @@ bool p3GxsForums::createGroup(uint32_t &token, RsGxsForumGroup &group) bool p3GxsForums::updateGroup(uint32_t &token, RsGxsGroupUpdateMeta& meta, RsGxsForumGroup &group) { - std::cerr << "p3GxsForums::createGroup()" << std::endl; + std::cerr << "p3GxsForums::updateGroup()" << std::endl; if(meta.getGroupId().empty()) return false; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 96e0e6569..5864ae32d 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -29,6 +29,7 @@ #include "retroshare/rsiface.h" #include "util/rsrandom.h" #include "util/rsstring.h" +#include "util/radix64.h" #include "pqi/authgpg.h" @@ -39,10 +40,13 @@ /**** * #define DEBUG_IDS 1 + * #define DEBUG_RECOGN 1 * #define GXSID_GEN_DUMMY_DATA 1 * #define ENABLE_PGP_SIGNATURES 1 ****/ +#define DEBUG_IDS 1 +#define DEBUG_RECOGN 1 #define ENABLE_PGP_SIGNATURES 1 @@ -76,14 +80,16 @@ RsIdentity *rsIdentity = NULL; #define RSGXSID_MAX_SERVICE_STRING 1024 #define BG_PGPHASH 1 -#define BG_REPUTATION 2 +#define BG_RECOGN 2 +#define BG_REPUTATION 3 #define GXSIDREQ_CACHELOAD 0x0001 #define GXSIDREQ_CACHEOWNIDS 0x0002 #define GXSIDREQ_PGPHASH 0x0010 -#define GXSIDREQ_REPUTATION 0x0020 +#define GXSIDREQ_RECOGN 0x0020 +#define GXSIDREQ_REPUTATION 0x0030 #define GXSIDREQ_CACHETEST 0x1000 @@ -94,7 +100,10 @@ RsIdentity *rsIdentity = NULL; #define GXSID_EVENT_PGPHASH 0x0010 #define GXSID_EVENT_PGPHASH_PROC 0x0011 -#define GXSID_EVENT_REPUTATION 0x0020 +#define GXSID_EVENT_RECOGN 0x0020 +#define GXSID_EVENT_RECOGN_PROC 0x0021 + +#define GXSID_EVENT_REPUTATION 0x0030 #define GXSID_EVENT_CACHETEST 0x1000 @@ -115,6 +124,10 @@ RsIdentity *rsIdentity = NULL; #define PGPHASH_RETRY_PERIOD 11 #define PGPHASH_PROC_PERIOD 1 +#define RECOGN_PERIOD 90 +#define RECOGN_RETRY_PERIOD 17 +#define RECOGN_PROC_PERIOD 1 + #define REPUTATION_PERIOD 60 #define REPUTATION_RETRY_PERIOD 13 #define REPUTATION_PROC_PERIOD 1 @@ -126,14 +139,15 @@ RsIdentity *rsIdentity = NULL; p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *nes) : RsGxsIdExchange(gds, nes, new RsGxsIdSerialiser(), RS_SERVICE_GXSV2_TYPE_GXSID, idAuthenPolicy()), RsIdentity(this), GxsTokenQueue(this), RsTickEvent(), mIdMtx("p3IdService"), - mPublicKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPublicKeyCache"), - mPrivateKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPrivateKeyCache") + mPublicKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPublicKeyCache"), + mPrivateKeyCache(DEFAULT_MEM_CACHE_SIZE, "GxsIdPrivateKeyCache") { mBgSchedule_Mode = 0; mBgSchedule_Active = false; // Kick off Cache Testing, + Others. RsTickEvent::schedule_in(GXSID_EVENT_PGPHASH, PGPHASH_PERIOD); + RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, RECOGN_PERIOD); RsTickEvent::schedule_in(GXSID_EVENT_REPUTATION, REPUTATION_PERIOD); RsTickEvent::schedule_now(GXSID_EVENT_CACHEOWNIDS); @@ -146,6 +160,7 @@ p3IdService::p3IdService(RsGeneralDataService *gds, RsNetworkExchangeService *ne #endif #endif + loadRecognKeys(); } @@ -300,6 +315,81 @@ bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms) return true; } +bool p3IdService::updateIdentity(uint32_t& token, RsGxsIdGroup &group) +{ + std::cerr << "p3IdService::updateIdentity()"; + std::cerr << std::endl; + + updateGroup(token, group); + + return false; +} + + +bool p3IdService::parseRecognTag(const RsGxsId &id, const std::string &nickname, + const std::string &tag, RsRecognTagDetails &details) +{ + std::cerr << "p3IdService::parseRecognTag()"; + std::cerr << std::endl; + + RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(tag); + if (!tagitem) + { + return false; + } + + bool isPending = false; + bool isValid = recogn_checktag(id, nickname, tagitem, true, isPending); + + details.valid_from = tagitem->valid_from; + details.valid_to = tagitem->valid_to; + details.tag_class = tagitem->tag_class; + details.tag_type = tagitem->tag_type; + details.signer = tagitem->sign.keyId; + + details.is_valid = isValid; + details.is_pending = isPending; + + delete tagitem; + + return true; +} + +bool p3IdService::getRecognTagRequest(const RsGxsId &id, const std::string &comment, uint16_t tag_class, uint16_t tag_type, std::string &tag) +{ + std::cerr << "p3IdService::getRecognTagRequest()"; + std::cerr << std::endl; + + if (!havePrivateKey(id)) + { + std::cerr << "p3IdService::getRecognTagRequest() Dont have private key"; + std::cerr << std::endl; + // attempt to load it. + cache_request_load(id); + return false; + } + + RsTlvSecurityKey key; + std::string nickname; + + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + RsGxsIdCache data; + if (!mPrivateKeyCache.fetch(id, data)) + { + std::cerr << "p3IdService::getRecognTagRequest() Cache failure"; + std::cerr << std::endl; + return false; + } + + key = data.pubkey; + nickname = data.details.mNickname; + } + + return RsRecogn::createTagRequest(key, id, nickname, tag_class, tag_type, comment, tag); +} + + /********************************************************************************/ /******************* RsGixs Interface ***************************************/ @@ -409,6 +499,12 @@ bool p3IdService::getGroupData(const uint32_t &token, std::vector RsGxsIdGroupItem* item = dynamic_cast(*vit); if (item) { +#ifdef DEBUG_IDS + std::cerr << "p3IdService::getGroupData() Item is:"; + std::cerr << std::endl; + item->print(std::cerr); + std::cerr << std::endl; +#endif // DEBUG_IDS RsGxsIdGroup group = item->group; group.mMeta = item->meta; @@ -493,20 +589,64 @@ bool p3IdService::getMsgData(const uint32_t &token, std::vector bool p3IdService::createGroup(uint32_t& token, RsGxsIdGroup &group) { - RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); - item->group = group; - item->meta = group.mMeta; - RsGenExchange::publishGroup(token, item); - return true; + RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + item->group = group; + item->meta = group.mMeta; + RsGenExchange::publishGroup(token, item); + return true; +} + +bool p3IdService::updateGroup(uint32_t& token, RsGxsIdGroup &group) +{ + RsGxsId id = group.mMeta.mGroupId; + RsGxsIdGroupItem* item = new RsGxsIdGroupItem(); + item->group = group; + item->meta = group.mMeta; + + std::cerr << "p3IdService::updateGroup() Updating RsGxsId: " << id; + std::cerr << std::endl; + + //RsGenExchange::updateGroup(token, item); + + RsGxsGroupUpdateMeta updateMeta(id); + RsGenExchange::updateGroup(token, updateMeta, item); + + // if its in the cache - clear it. + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (mPublicKeyCache.erase(id)) + { + std::cerr << "p3IdService::updateGroup() Removed from PublicKeyCache"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3IdService::updateGroup() Not in PublicKeyCache"; + std::cerr << std::endl; + } + + if (mPrivateKeyCache.erase(id)) + { + std::cerr << "p3IdService::updateGroup() Removed from PrivateKeyCache"; + std::cerr << std::endl; + } + else + { + std::cerr << "p3IdService::updateGroup() Not in PrivateKeyCache"; + std::cerr << std::endl; + } + } + + return true; } bool p3IdService::createMsg(uint32_t& token, RsGxsIdOpinion &opinion) { - RsGxsIdOpinionItem* item = new RsGxsIdOpinionItem(); - item->opinion = opinion; - item->meta = opinion.mMeta; - RsGenExchange::publishMsg(token, item); - return true; + RsGxsIdOpinionItem* item = new RsGxsIdOpinionItem(); + item->opinion = opinion; + item->meta = opinion.mMeta; + RsGenExchange::publishMsg(token, item); + return true; } /************************************************************************************/ @@ -558,6 +698,85 @@ std::string SSGxsIdPgp::save() const return output; } + +/* Encoding / Decoding Group Service String stuff + * + * RecognTags. + */ + +bool SSGxsIdRecognTags::load(const std::string &input) +{ + char pgpline[RSGXSID_MAX_SERVICE_STRING]; + int pubTs = 0; + int lastTs = 0; + uint32_t flags = 0; + + if (3 == sscanf(input.c_str(), "F:%u P:%d T:%d", &flags, &pubTs, &lastTs)) + { + publishTs = pubTs; + lastCheckTs = lastTs; + tagFlags = flags; + } + else + { + return false; + } + return true; +} + +std::string SSGxsIdRecognTags::save() const +{ + std::string output; + rs_sprintf(output, "F:%u P:%d T:%d", tagFlags, publishTs, lastCheckTs); + return output; +} + +bool SSGxsIdRecognTags::tagsProcessed() const +{ + return (tagFlags & 0x1000); +} + +bool SSGxsIdRecognTags::tagsPending() const +{ + return (tagFlags & 0x2000); +} + +bool SSGxsIdRecognTags::tagValid(int i) const +{ + uint32_t idx = 0x01 << i; + +#ifdef DEBUG_RECOGN + std::cerr << "SSGxsIdRecognTags::tagValid(" << i << ") idx: " << idx; + std::cerr << " result: " << (tagFlags & idx); + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + return (tagFlags & idx); +} + +void SSGxsIdRecognTags::setTags(bool processed, bool pending, uint32_t flags) +{ + flags &= 0x00ff; // clear top bits; + if (processed) + { + flags |= 0x1000; + } + if (pending) + { + flags |= 0x2000; + } + +#ifdef DEBUG_RECOGN + std::cerr << "SSGxsIdRecognTags::setTags(" << processed << "," << pending << "," << flags << ")"; + std::cerr << " tagFlags: " << tagFlags; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + tagFlags = flags; +} + + + bool SSGxsIdScore::load(const std::string &input) { return (1 == sscanf(input.c_str(), "%d", &score)); @@ -585,12 +804,13 @@ std::string SSGxsIdCumulator::save() const bool SSGxsIdGroup::load(const std::string &input) { char pgpstr[RSGXSID_MAX_SERVICE_STRING]; + char recognstr[RSGXSID_MAX_SERVICE_STRING]; char scorestr[RSGXSID_MAX_SERVICE_STRING]; char opinionstr[RSGXSID_MAX_SERVICE_STRING]; char repstr[RSGXSID_MAX_SERVICE_STRING]; - // split into two parts. - if (4 != sscanf(input.c_str(), "v1 {P:%[^}]} {Y:%[^}]} {O:%[^}]} {R:%[^}]}", pgpstr, scorestr, opinionstr, repstr)) + // split into parts. + if (5 != sscanf(input.c_str(), "v1 {P:%[^}]} {T:%[^}]} {Y:%[^}]} {O:%[^}]} {R:%[^}]}", pgpstr, recognstr, scorestr, opinionstr, repstr)) { #ifdef DEBUG_IDS std::cerr << "SSGxsIdGroup::load() Failed to extract 4 Parts"; @@ -616,6 +836,22 @@ bool SSGxsIdGroup::load(const std::string &input) ok = false; } + if (recogntags.load(recognstr)) + { +#ifdef DEBUG_RECOGN + std::cerr << "SSGxsIdGroup::load() recognstr: " << recognstr; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "SSGxsIdGroup::load() Invalid recognstr: " << recognstr; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + ok = false; + } + if (score.load(scorestr)) { #ifdef DEBUG_IDS @@ -682,6 +918,10 @@ std::string SSGxsIdGroup::save() const output += pgp.save(); output += "}"; + output += "{T:"; + output += recogntags.save(); + output += "}"; + output += "{Y:"; output += score.save(); output += "}"; @@ -725,11 +965,17 @@ RsGxsIdCache::RsGxsIdCache() return; } -RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey) +RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey, const std::list &tagList) { // Save Keys. pubkey = in_pkey; + // Save Time for ServiceString comparisions. + mPublishTs = item->meta.mPublishTs; + + // Save RecognTags. + mRecognTags = tagList; + // Fill in Details. details.mNickname = item->meta.mGroupName; details.mId = item->meta.mGroupId; @@ -749,6 +995,8 @@ RsGxsIdCache::RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey void RsGxsIdCache::updateServiceString(std::string serviceString) { + details.mRecognTags.clear(); + SSGxsIdGroup ssdata; if (ssdata.load(serviceString)) { @@ -765,6 +1013,54 @@ void RsGxsIdCache::updateServiceString(std::string serviceString) } } + + // process RecognTags. + if (ssdata.recogntags.tagsProcessed()) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsGxsIdCache::updateServiceString() updating recogntags"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + if (ssdata.recogntags.publishTs == mPublishTs) + { + std::list::iterator it; + int i = 0; + for(it = mRecognTags.begin(); it != mRecognTags.end(); it++, i++) + { + if (ssdata.recogntags.tagValid(i) && it->valid) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsGxsIdCache::updateServiceString() Valid Tag: " << it->tag_class << ":" << it->tag_type; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + details.mRecognTags.push_back(*it); + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "RsGxsIdCache::updateServiceString() Invalid Tag: " << it->tag_class << ":" << it->tag_type; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + } + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "RsGxsIdCache::updateServiceString() recogntags old publishTs"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "RsGxsIdCache::updateServiceString() recogntags unprocessed"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + details.mOpinion = 0; details.mReputation = ssdata.score.score; } @@ -779,9 +1075,137 @@ void RsGxsIdCache::updateServiceString(std::string serviceString) } +bool p3IdService::recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems) +{ +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_extract_taginfo()"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + /* process Recogn Tags */ + + std::list::const_iterator rit; + int count = 0; + for(rit = item->group.mRecognTags.begin(); rit != item->group.mRecognTags.end(); rit++) + { + if (++count > RSRECOGN_MAX_TAGINFO) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_extract_taginfo() Too many tags."; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + return true; + } + + RsGxsRecognTagItem *tagitem = RsRecogn::extractTag(*rit); + + if (!tagitem) + { + continue; + } + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_extract_taginfo() Got TagItem: "; + std::cerr << std::endl; + tagitem->print(std::cerr); +#endif // DEBUG_RECOGN + + tagItems.push_back(tagitem); + } + return true; +} +bool p3IdService::cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList) +{ + /* ServiceString decode */ + SSGxsIdGroup ssdata; + bool recognProcess = false; + if (ssdata.load(item->meta.mServiceString)) + { + if (!ssdata.recogntags.tagsProcessed()) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() tags not processed"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + /* we need to reprocess it */ + recognProcess = true; + } + else + { + if (item->meta.mPublishTs != ssdata.recogntags.publishTs) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() publishTs old"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + recognProcess = true; + } + else if (ssdata.recogntags.tagsPending()) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() tagsPending"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + /* reprocess once a day */ + recognProcess = true; + } + } + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() ServiceString invalid"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + recognProcess = true; + } + + std::list tagItems; + std::list::iterator it; + + recogn_extract_taginfo(item, tagItems); + + time_t now = time(NULL); + for(it = tagItems.begin(); it != tagItems.end(); it++) + { + RsRecognTag info((*it)->tag_class, (*it)->tag_type, false); + bool isPending = false; + if (recogn_checktag(item->meta.mGroupId, item->meta.mGroupName, *it, false, isPending)) + { + info.valid = true; + } +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() Adding Tag: "; + std::cerr << info.tag_class << ":"; + std::cerr << info.tag_type << ":"; + std::cerr << info.valid; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + tagList.push_back(info); + delete *it; + } + + + if (recognProcess) + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mRecognGroupIds.push_back(item->meta.mGroupId); + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::cache_process_recogntaginfo() Reprocessing groupId: "; + std::cerr << item->meta.mGroupId; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + } + + return true; +} bool p3IdService::cache_store(const RsGxsIdGroupItem *item) @@ -793,7 +1217,7 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item) //item->print(std::cerr, 0); NEEDS CONST!!!! TODO //std::cerr << std::endl; - /* extract key from keys */ + /* extract key from keys */ RsTlvSecurityKeySet keySet; RsTlvSecurityKey pubkey; RsTlvSecurityKey fullkey; @@ -814,9 +1238,9 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item) //std::cerr << "p3IdService::cache_store() KeySet is:"; //keySet.print(std::cerr, 10); - for (kit = keySet.keys.begin(); kit != keySet.keys.end(); kit++) - { - if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) + for (kit = keySet.keys.begin(); kit != keySet.keys.end(); kit++) + { + if (kit->second.keyFlags & RSTLV_KEY_DISTRIB_ADMIN) { #ifdef DEBUG_IDS std::cerr << "p3IdService::cache_store() Found Admin Key"; @@ -824,7 +1248,7 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item) #endif // DEBUG_IDS /* save full key - if we have it */ - if (kit->second.keyFlags & RSTLV_KEY_TYPE_FULL) + if (kit->second.keyFlags & RSTLV_KEY_TYPE_FULL) { fullkey = kit->second; full_key_ok = true; @@ -847,16 +1271,20 @@ bool p3IdService::cache_store(const RsGxsIdGroupItem *item) return false; } + // extract tags. + std::list tagList; + cache_process_recogntaginfo(item, tagList); + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ // Create Cache Data. - RsGxsIdCache pubcache(item, pubkey); + RsGxsIdCache pubcache(item, pubkey, tagList); mPublicKeyCache.store(id, pubcache); mPublicKeyCache.resize(); if (full_key_ok) { - RsGxsIdCache fullcache(item, fullkey); + RsGxsIdCache fullcache(item, fullkey, tagList); mPrivateKeyCache.store(id, fullcache); mPrivateKeyCache.resize(); } @@ -932,8 +1360,8 @@ bool p3IdService::cache_start_load() #endif // DEBUG_IDS uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token = 0; RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, groupIds); @@ -1041,8 +1469,8 @@ bool p3IdService::cache_request_ownids() uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + //opts.mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN; uint32_t token = 0; @@ -1132,8 +1560,8 @@ bool p3IdService::cachetest_getlist() #endif // DEBUG_IDS uint32_t ansType = RS_TOKREQ_ANSTYPE_LIST; - RsTokReqOptions opts; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_IDS; uint32_t token = 0; RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); @@ -1154,11 +1582,11 @@ bool p3IdService::cachetest_handlerequest(uint32_t token) std::list grpIds; bool ok = RsGenExchange::getGroupList(token, grpIds); - if(ok) - { - std::list::iterator vit = grpIds.begin(); - for(; vit != grpIds.end(); vit++) - { + if(ok) + { + std::list::iterator vit = grpIds.begin(); + for(; vit != grpIds.end(); vit++) + { /* 5% chance of checking it! */ if (RSRandom::random_f32() < 0.25) { @@ -1189,7 +1617,7 @@ bool p3IdService::cachetest_handlerequest(uint32_t token) #endif // DEBUG_IDS // success! - seckey.print(std::cerr, 10); + seckey.print(std::cerr, 10); std::cerr << std::endl; @@ -1229,7 +1657,7 @@ bool p3IdService::cachetest_handlerequest(uint32_t token) } } } - } + } else { std::cerr << "p3IdService::cache_load_for_token() ERROR no data"; @@ -1245,13 +1673,13 @@ bool p3IdService::cachetest_handlerequest(uint32_t token) /************************************************************************************/ /* - * We have two background tasks that use the ServiceString: PGPHash & Reputation. + * We have three background tasks that use the ServiceString: PGPHash & Reputation & Recogn * * Only one task can be run at a time - otherwise potential overwrite issues. * So this part coordinates that part of the code. * - * - * + * We are going to have a "fetcher task", which gets all the UNPROCESSED / UPDATED GROUPS. + * and sets the CHECK_PGP, CHECK_RECOGN, etc... this will reduce the "Get All" calls. * */ @@ -1263,7 +1691,7 @@ bool p3IdService::CacheArbitration(uint32_t mode) if (!mBgSchedule_Active) { #ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Okay"; + std::cerr << "p3IdService::CacheArbitration() Okay: mode " << mode; std::cerr << std::endl; #endif // DEBUG_IDS @@ -1273,7 +1701,7 @@ bool p3IdService::CacheArbitration(uint32_t mode) } #ifdef DEBUG_IDS - std::cerr << "p3IdService::CacheArbitration() Is busy..."; + std::cerr << "p3IdService::CacheArbitration() Is busy in mode: " << mBgSchedule_Mode; std::cerr << std::endl; #endif // DEBUG_IDS @@ -1347,6 +1775,13 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte return SERVICE_CREATE_FAIL; } +#ifdef DEBUG_IDS + std::cerr << "p3IdService::service_CreateGroup() Item is:"; + std::cerr << std::endl; + item->print(std::cerr); + std::cerr << std::endl; +#endif // DEBUG_IDS + /********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/ // find private admin key std::map::iterator mit = keySet.keys.begin(); @@ -1539,11 +1974,9 @@ bool p3IdService::pgphash_start() // Also need to use opts.groupFlags to filter stuff properly to REALID's only. // TODO - //uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; - RsTokReqOptions opts; - //opts.mReqType = GXS_REQUEST_TYPE_GROUP_META; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; uint32_t token = 0; RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts); @@ -1711,29 +2144,6 @@ bool p3IdService::pgphash_process() ssdata.pgp.idKnown = true; ssdata.pgp.pgpId = pgpId.toStdString(); -// SHOULD BE PUSHED TO CACHE! -#if 0 - id.mGpgIdKnown = true; - - id.mGpgId = *it; - id.mGpgName = details.name; - id.mGpgEmail = details.email; - - if (*it == ownId) - { - id.mIdType |= RSID_RELATION_YOURSELF; - } - else if (rsPeers->isGPGAccepted(*it)) - { - id.mIdType |= RSID_RELATION_FRIEND; - } - else - { - id.mIdType |= RSID_RELATION_OTHER; - } - -#endif - } else { @@ -1768,7 +2178,7 @@ bool p3IdService::checkId(const RsGxsIdGroup &grp, PGPIdType &pgpId) std::cerr << std::endl; #endif // DEBUG_IDS - /* some sanity checking... make sure hash is the right size */ + /* some sanity checking... make sure hash is the right size */ #ifdef DEBUG_IDS std::cerr << "p3IdService::checkId() PgpIdHash is: " << grp.mPgpIdHash; @@ -1903,13 +2313,13 @@ void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash { unsigned char signature[SHA_DIGEST_LENGTH]; /* hash id + pubkey => pgphash */ - SHA_CTX *sha_ctx = new SHA_CTX; - SHA1_Init(sha_ctx); + SHA_CTX *sha_ctx = new SHA_CTX; + SHA1_Init(sha_ctx); - SHA1_Update(sha_ctx, id.c_str(), id.length()); // TO FIX ONE DAY. - SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); - SHA1_Final(signature, sha_ctx); - hash = GxsIdPgpHash(signature); + SHA1_Update(sha_ctx, id.c_str(), id.length()); // TO FIX ONE DAY. + SHA1_Update(sha_ctx, pgp.toByteArray(), pgp.SIZE_IN_BYTES); + SHA1_Final(signature, sha_ctx); + hash = GxsIdPgpHash(signature); #ifdef DEBUG_IDS std::cerr << "calcPGPHash():"; @@ -1922,9 +2332,325 @@ void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdPgpHash std::cerr << std::endl; #endif // DEBUG_IDS - delete sha_ctx; + delete sha_ctx; } +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ +/************************************************************************************/ + +/* Task to validate Recogn Tags. + * + * Info to be stored in GroupServiceString + Cache. + **/ + + +bool p3IdService::recogn_start() +{ + if (!CacheArbitration(BG_RECOGN)) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_start() Other Events running... Rescheduling"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + /* reschedule in a bit */ + RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, RECOGN_RETRY_PERIOD); + return false; + } + + // SCHEDULE NEXT ONE. + RsTickEvent::schedule_in(GXSID_EVENT_RECOGN, RECOGN_PERIOD); + + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_start() making request"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + std::list recognList; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + recognList = mRecognGroupIds; + mRecognGroupIds.clear(); + } + + if (recognList.empty()) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_start() List is Empty, cancelling"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + // FINISHED. + CacheArbitrationDone(BG_RECOGN); + return false; + } + + uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; + RsTokReqOptions opts; + opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; + uint32_t token = 0; + + RsGenExchange::getTokenService()->requestGroupInfo(token, ansType, opts, recognList); + GxsTokenQueue::queueRequest(token, GXSIDREQ_RECOGN); + return true; + +} + + +bool p3IdService::recogn_handlerequest(uint32_t token) +{ +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_handlerequest(" << token << ")"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + std::vector grpData; + bool ok = RsGenExchange::getGroupData(token, grpData); + + if(ok) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_request() Have " << grpData.size() << " Groups"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + std::vector::iterator vit = grpData.begin(); + + for(; vit != grpData.end(); vit++) + { + RsGxsIdGroupItem* item = dynamic_cast(*vit); + if (item) + { + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_request() Group Id: " << item->meta.mGroupId; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + mRecognGroupsToProcess.push_back(item); + } + else + { + delete (*vit); + } + } + } + else + { + std::cerr << "p3IdService::recogn_request() getGroupData ERROR"; + std::cerr << std::endl; + } + + // Schedule Processing. + RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); + return true; +} + + +bool p3IdService::recogn_process() +{ + /* each time this is called - process one Id from mGroupsToProcess */ + RsGxsIdGroupItem *item; + bool isDone = false; + { + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + if (!mRecognGroupsToProcess.empty()) + { + item = mRecognGroupsToProcess.front(); + mGroupsToProcess.pop_front(); + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_process() Popped Group: " << item->meta.mGroupId; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + else + { + isDone = true; + } + } + + if (isDone) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_process() List Empty... Done"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + // FINISHED. + CacheArbitrationDone(BG_RECOGN); + return true; + } + + + + std::list tagItems; + std::list::iterator it; + + recogn_extract_taginfo(item, tagItems); + + bool isPending = false; + int i = 1; + uint32_t tagValidFlags = 0; + for(it = tagItems.begin(); it != tagItems.end(); it++) + { + bool isTagPending = false; + bool isTagOk = recogn_checktag(item->meta.mGroupId, item->meta.mGroupName, *it, true, isPending); + if (isTagOk) + { + tagValidFlags |= i; + } + else + { + isPending |= isTagPending; + } + + delete *it; + i *= 2; + } + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_process() Tags Checked, saving"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + SSGxsIdGroup ssdata; + ssdata.load(item->meta.mServiceString); // attempt load - okay if fails. + + ssdata.recogntags.setTags(true, isPending, tagValidFlags); + ssdata.recogntags.lastCheckTs = time(NULL); + ssdata.recogntags.publishTs = item->meta.mPublishTs; + + /* set new Group ServiceString */ + uint32_t dummyToken = 0; + std::string serviceString = ssdata.save(); + setGroupServiceString(dummyToken, item->meta.mGroupId, serviceString); + + cache_update_if_cached(item->meta.mGroupId, serviceString); + + delete item; + + // Schedule Next Processing. + RsTickEvent::schedule_in(GXSID_EVENT_RECOGN_PROC, RECOGN_PROC_PERIOD); + return false; // as there are more items on the queue to process. +} + + +bool p3IdService::recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending) +{ + +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() groupId: " << id; + std::cerr << std::endl; + std::cerr << "p3IdService::recogn_checktag() nickname: " << nickname; + std::cerr << std::endl; + std::cerr << "p3IdService::recogn_checktag() item: "; + std::cerr << std::endl; + ((RsGxsRecognTagItem *) item)->print(std::cerr); +#endif // DEBUG_RECOGN + + // To check: + // ------------------- + // date range. + // id matches. + // nickname matches. + // signer is valid. + // ------ + // signature is valid. (only if doSignCheck == true) + + time_t now = time(NULL); + isPending = false; + + // check date range. + if ((item->valid_from > now) || (item->valid_to < now)) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() failed timestamp"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + return false; + } + + // id match. + if (id != item->identity) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() failed identity"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + // nickname match. + if (nickname != item->nickname) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() failed nickname"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + + + { + /* check they validity of the Tag */ + RsStackMutex stack(mIdMtx); /********** STACK LOCKED MTX ******/ + + + std::map::iterator it; + it = mRecognSignKeys.find(item->sign.keyId); + if (it == mRecognSignKeys.end()) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() failed to find signkey"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + + // If OldKey, then we don't want to reprocess. + if (mRecognOldSignKeys.end() != + mRecognOldSignKeys.find(item->sign.keyId)) + { + isPending = true; // need to reprocess later with new key + } + return false; + } + + // Check tag_class is okay for signer. + if (it->second->signing_classes.ids.end() == + std::find(it->second->signing_classes.ids.begin(), it->second->signing_classes.ids.end(), item->tag_class)) + { +#ifdef DEBUG_RECOGN + std::cerr << "p3IdService::recogn_checktag() failed signing_class check"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + // ALL Okay, just signature to check. + if (!doSignCheck) + { + return true; + } + + return RsRecogn::validateTagSignature(it->second, item); + } +} + + +void p3IdService::loadRecognKeys() +{ + RsStackMutex stack(mIdMtx); /**** LOCKED MUTEX ****/ + + RsRecogn::loadSigningKeys(mRecognSignKeys); +} + + /************************************************************************************/ /************************************************************************************/ @@ -2003,13 +2729,13 @@ void p3IdService::generateDummy_OwnIds() for(i = 0; i < nIds; i++) { RsGxsIdGroup id; - RsPeerDetails details; + RsPeerDetails details; id.mMeta.mGroupFlags = RSGXSID_GROUPFLAG_REALID; // HACK FOR DUMMY GENERATION. id.mMeta.mAuthorId = ownId; - if (rsPeers->getPeerDetails(ownId, details)) + if (rsPeers->getPeerDetails(ownId, details)) { std::ostringstream out; out << details.name << "_" << i + 1; @@ -2339,7 +3065,7 @@ bool p3IdService::background_checkTokenRequest() uint32_t anstype; time_t ts; - + status = RsGenExchange::getTokenService()->requestStatus(token); //checkRequestStatus(token, status, reqtype, anstype, ts); @@ -2390,7 +3116,7 @@ bool p3IdService::background_requestGroups() } uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; + RsTokReqOptions opts; std::list groupIds; /** @@ -2445,7 +3171,7 @@ bool p3IdService::background_requestNewMessages() for(it = modGroupList.begin(); it != modGroupList.end(); it++) { /*** TODO - uint32_t dummyToken = 0; + uint32_t dummyToken = 0; setGroupStatusFlags(dummyToken, it->mGroupId, 0, RSGXS_GROUP_STATUS_NEWMSG); ***/ @@ -2455,7 +3181,7 @@ bool p3IdService::background_requestNewMessages() } uint32_t ansType = RS_TOKREQ_ANSTYPE_SUMMARY; - RsTokReqOptions opts; + RsTokReqOptions opts; token = 0; /* TODO @@ -2501,7 +3227,7 @@ bool p3IdService::background_processNewMessages() * and flag these items as modified - so we rewrite them to the db later. * * If a message is not an original -> store groupId for requiring full analysis later. - */ + */ std::map::iterator mit; @@ -2639,7 +3365,7 @@ bool p3IdService::background_processNewMessages() #endif // DEBUG_IDS /* set Cache */ - uint32_t dummyToken = 0; + uint32_t dummyToken = 0; setGroupServiceString(dummyToken, mit->second.mGroupId, mit->second.mServiceString); } else @@ -2688,7 +3414,7 @@ bool p3IdService::background_FullCalcRequest() /* request the summary info from the parents */ uint32_t ansType = RS_TOKREQ_ANSTYPE_DATA; uint32_t token = 0; - RsTokReqOptions opts; + RsTokReqOptions opts; opts.mOptions = RS_TOKREQOPT_MSG_LATEST; RsGenExchange::getTokenService()->requestMsgInfo(token, ansType, opts, groupIds); @@ -2727,10 +3453,10 @@ bool p3IdService::background_processFullCalc() double rep_sum = 0; double rep_sumsq = 0; - std::vector opinions; - std::vector::iterator vit; + std::vector opinions; + std::vector::iterator vit; - if (!getMsgData(mBgToken, opinions)) + if (!getMsgData(mBgToken, opinions)) { std::cerr << "p3IdService::background_processFullCalc() ERROR Failed to get Opinions"; std::cerr << std::endl; @@ -2739,7 +3465,7 @@ bool p3IdService::background_processFullCalc() } std::string groupId; - for(vit = opinions.begin(); vit != opinions.end(); vit++) + for(vit = opinions.begin(); vit != opinions.end(); vit++) { RsGxsIdOpinion &opinion = *vit; @@ -2878,7 +3604,7 @@ std::ostream &operator<<(std::ostream &out, const RsGxsIdOpinion &opinion) - // Overloaded from GxsTokenQueue for Request callbacks. +// Overloaded from GxsTokenQueue for Request callbacks. void p3IdService::handleResponse(uint32_t token, uint32_t req_type) { #ifdef DEBUG_IDS @@ -2898,6 +3624,9 @@ void p3IdService::handleResponse(uint32_t token, uint32_t req_type) case GXSIDREQ_PGPHASH: pgphash_handlerequest(token); break; + case GXSIDREQ_RECOGN: + recogn_handlerequest(token); + break; case GXSIDREQ_CACHETEST: cachetest_handlerequest(token); break; @@ -2949,6 +3678,14 @@ void p3IdService::handle_event(uint32_t event_type, const std::string &elabel) pgphash_process(); break; + case GXSID_EVENT_RECOGN: + recogn_start(); + break; + + case GXSID_EVENT_RECOGN_PROC: + recogn_process(); + break; + case GXSID_EVENT_DUMMYDATA: generateDummyData(); break; diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index e9560e8df..a42712ed4 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -38,9 +38,12 @@ #include "util/rsmemcache.h" #include "util/rstickevent.h" +#include "util/rsrecogn.h" #include "pqi/authgpg.h" +#include "serialiser/rsgxsrecognitems.h" + /* * Identity Service * @@ -73,6 +76,27 @@ virtual std::string save() const; std::string pgpId; }; +class SSGxsIdRecognTags: public SSBit +{ + public: + SSGxsIdRecognTags() + :tagFlags(0), publishTs(0), lastCheckTs(0) { return; } + +virtual bool load(const std::string &input); +virtual std::string save() const; + + void setTags(bool processed, bool pending, uint32_t flags); + + bool tagsProcessed() const; // have we processed? + bool tagsPending() const; // should we reprocess? + bool tagValid(int i) const; + + time_t publishTs; + time_t lastCheckTs; + uint32_t tagFlags; +}; + + class SSGxsIdScore: public SSBit { public: @@ -113,11 +137,14 @@ virtual std::string save() const; // pgphash status SSGxsIdPgp pgp; + // recogTags. + SSGxsIdRecognTags recogntags; + // reputation score. SSGxsIdScore score; SSGxsIdCumulator opinion; SSGxsIdCumulator reputation; - + }; #define ID_LOCAL_STATUS_FULL_CALC_FLAG 0x00010000 @@ -133,10 +160,14 @@ class RsGxsIdCache { public: RsGxsIdCache(); - RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey); + RsGxsIdCache(const RsGxsIdGroupItem *item, const RsTlvSecurityKey &in_pkey, + const std::list &tagList); void updateServiceString(std::string serviceString); + time_t mPublishTs; + std::list mRecognTags; // Only partially validated. + RsIdentityDetails details; RsTlvSecurityKey pubkey; }; @@ -175,6 +206,7 @@ virtual bool getMsgData(const uint32_t &token, std::vector &opin // These are local - and not exposed via RsIdentity. virtual bool createGroup(uint32_t& token, RsGxsIdGroup &group); +virtual bool updateGroup(uint32_t& token, RsGxsIdGroup &group); virtual bool createMsg(uint32_t& token, RsGxsIdOpinion &opinion); /**************** RsIdentity External Interface. @@ -197,6 +229,13 @@ virtual bool getOwnIds(std::list &ownIds); virtual bool submitOpinion(uint32_t& token, RsIdOpinion &opinion); virtual bool createIdentity(uint32_t& token, RsIdentityParameters ¶ms); +virtual bool updateIdentity(uint32_t& token, RsGxsIdGroup &group); + +virtual bool parseRecognTag(const RsGxsId &id, const std::string &nickname, + const std::string &tag, RsRecognTagDetails &details); +virtual bool getRecognTagRequest(const RsGxsId &id, const std::string &comment, + uint16_t tag_class, uint16_t tag_type, std::string &tag); + /**************** RsGixs Implementation * Notes: @@ -303,6 +342,32 @@ virtual void handle_event(uint32_t event_type, const std::string &elabel); std::map mPgpFingerprintMap; std::list mGroupsToProcess; +/************************************************************************ + * recogn processing. + * + */ + bool recogn_start(); + bool recogn_handlerequest(uint32_t token); + bool recogn_process(); + + // helper functions. + bool recogn_extract_taginfo(const RsGxsIdGroupItem *item, std::list &tagItems); + bool cache_process_recogntaginfo(const RsGxsIdGroupItem *item, std::list &tagList); + + bool recogn_checktag(const RsGxsId &id, const std::string &nickname, RsGxsRecognTagItem *item, bool doSignCheck, bool &isPending); + + void loadRecognKeys(); + + /* MUTEX PROTECTED DATA (mIdMtx - maybe should use a 2nd?) */ + + bool checkRecognSignature_locked(std::string encoded, RSA &key, std::string signature); + bool getRecognKey_locked(std::string signer, RSA &key); + + std::list mRecognGroupIds; + std::list mRecognGroupsToProcess; + std::map mRecognSignKeys; + std::map mRecognOldSignKeys; + /************************************************************************ * Below is the background task for processing opinions => reputations * diff --git a/libretroshare/src/services/p3posted.cc b/libretroshare/src/services/p3posted.cc index b6afe5e2d..46a4220a0 100644 --- a/libretroshare/src/services/p3posted.cc +++ b/libretroshare/src/services/p3posted.cc @@ -40,7 +40,6 @@ /**** * #define POSTED_DEBUG 1 ****/ -#define POSTED_DEBUG 1 RsPosted *rsPosted = NULL; diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc index 9446e8686..5813fd84e 100644 --- a/libretroshare/src/turtle/rsturtleitem.cc +++ b/libretroshare/src/turtle/rsturtleitem.cc @@ -544,7 +544,7 @@ RsTurtleGenericDataItem::RsTurtleGenericDataItem(void *data,uint32_t pktsize) if(data_bytes != NULL) { - memcpy(data_bytes,data+offset,data_size) ; + memcpy(data_bytes,(void *)((uint8_t *)data+offset),data_size) ; offset += data_size ; } else @@ -585,7 +585,7 @@ bool RsTurtleGenericDataItem::serialize(void *data,uint32_t& pktsize) ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); ok &= setRawUInt32(data, tlvsize, &offset, data_size); - memcpy(data+offset,data_bytes,data_size) ; + memcpy((void *)((uint8_t *)data+offset),data_bytes,data_size) ; offset += data_size ; if (offset != tlvsize) diff --git a/libretroshare/src/util/rsmemcache.h b/libretroshare/src/util/rsmemcache.h index 5c12e3183..0f5fb966f 100644 --- a/libretroshare/src/util/rsmemcache.h +++ b/libretroshare/src/util/rsmemcache.h @@ -65,6 +65,7 @@ template class RsMemCache bool fetch(const Key &key, Value &data); Value &ref(const Key &key); // like map[] installs empty one if non-existent. bool store(const Key &key, const Value &data); + bool erase(const Key &key); // clean up cache. bool resize(); // should be called periodically to cleanup old entries. @@ -169,6 +170,47 @@ template bool RsMemCache::fetch(const Key &k } +template bool RsMemCache::erase(const Key &key) +{ +#ifdef DEBUG_RSMEMCACHE + std::cerr << "RsMemCache::erase()"; + std::cerr << std::endl; + printStats(std::cerr); +#endif // DEBUG_RSMEMCACHE + + typename std::map::iterator it; + it = mDataMap.find(key); + if (it == mDataMap.end()) + { +#ifdef DEBUG_RSMEMCACHE + std::cerr << "RsMemCache::erase(" << key << ") false"; + std::cerr << std::endl; +#endif // DEBUG_RSMEMCACHE + + mStats_accessmiss++; + return false; + } + +#ifdef DEBUG_RSMEMCACHE + std::cerr << "RsMemCache::erase(" << key << ") OK"; + std::cerr << std::endl; +#endif // DEBUG_RSMEMCACHE + + + /* get timestamps */ + time_t old_ts = it->second.ts; + time_t new_ts = 0; + + // remove from lru. + mDataMap.erase(it); + update_lrumap(key, old_ts, new_ts); + + mStats_access++; + return true; +} + + + template Value &RsMemCache::ref(const Key &key) { #ifdef DEBUG_RSMEMCACHE diff --git a/libretroshare/src/util/rsrecogn.cc b/libretroshare/src/util/rsrecogn.cc new file mode 100644 index 000000000..19c189c6b --- /dev/null +++ b/libretroshare/src/util/rsrecogn.cc @@ -0,0 +1,640 @@ +/* + * libretroshare/src/util: rsrecogn.cc + * + * RetroShare Utilities + * + * Copyright 2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include +#include + +#include "pqi/pqi_base.h" + +#include "util/rsrecogn.h" +#include "util/radix64.h" +#include "util/rsstring.h" + +#include "gxs/gxssecurity.h" + +/*** + * #define DEBUG_RECOGN 1 + ***/ + +#define DEBUG_RECOGN 1 + +static std::string RecognKey = "MIICCgKCAgEA4/i2fy+zR27/H8fzphM8mR/Nz+yXjMJTtqKlCvEMQlyk7lKzDbKifNjGSiAXjSv3b9TRgMtje7hfEhs3//Oeu4KsCf6sz17aj2StBF579IdJTSUPDwq6jCsZ6NDEYpG8xz3FVV+Ac8q5Vpr/+jdg23ta09zq4aV8VIdIsroVOmZQqjwPcmQK57iWHd538i/XBtc2rnzbYq5bprnmtAKdx55gXVXDfALa0s6yR0HYvCaWguMEJhMIKWfi/9PEgLgwF9OmRwywc2TU/EdvYJo8fYHLfGk0PnYBuL1oSnn3cwAAef02W2JyCzQ84g30tLSUk+hC1LLi+iYj3x7IRR4q7Rlf/FYv/Q5fvjRtPT9eqM6fKyJ9ZO4NjlrSPFGydNbgABzP6WMhBzFjUkEKS27bGmr8Qxdj3Zp0TvR2IkyM6oM+6YknuM4RndUEgC1ZxtoIhugMjm6HdMQmoaHNK3kXewgQB90HHqzKA/J1gok3NcqL8Yls5g0LHepVHsU4cuaIqQr5yr665ZTLU2oqn1HIdkgydBYYUt6G3eWJKXYRbDhWPthGo/HK+W+iw6cTGWxzlCZS40EU9efxz4mDuhow67jOe704lBP3kiYXu05Y5uspaYnuvrvIwaRWBYapyR9UmKktnY8xJYrZvrcZgCovAbiodTzWeYg37xjFfGgYNI8CAwEAAQ=="; + +#define NUM_RECOGN_SIGN_KEYS 3 +static std::string RecognSigningKeys[NUM_RECOGN_SIGN_KEYS] = +{ + "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmYjI2ZTUyNGFlZjczYmY3Y2MyMzUwNTc0ZTMyMjcxZWEAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCyblJK73O/fMI1BXTjInHqIWma62Z2r3K7/giT6Xm3k+lyNokvpR+I45XdEvPRmFVZmTU7XT2n3YiPDLe7y2r9fnYiLvBCdu+FBaVv5UQG8nvFGMLKbhdyRpOSBgDc+Y+8plMPn8jqgfNhLROMowmvDJQkJQjlm80d/9wj+VZ+tLiPPo8uOlghqNhdXDGK7HnfeLrJyD8kLEW7+4huaxR8IsLgjzuK8rovGLYCBcnx4TXvtbEeafJBBBt8S/GPeUaB1rxWpVV6fi+oBU6cvjbEqPzSalIrwNPyqlj+1SbL1jGEGEr1XIMzDa96SVsJ0F93lS3H9c8HdvByAifgzbPZAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBp1w449QGjchVotgHvGWRh18zpsDUHRv8PlRX1vXy8FMstTrnRjaDofFitmpJm8K6F1t/9jviCdB+BCvRzAS4SxER49YCBp04xZfX7c03xdq/e27jYRds2w6YHTiEgNi5v1cyWhrwDcCdefXRnHTH1UOw3jOoWnlnmM6jEsL39XI5fvsog9z8GxcG54APKA7JgiqhgMcrKRwNk74XJAzcjB6FS8xaV2gzpZZLNZ1TU+tJoLSiRqTU8UiAGbAR85lYLT5Ozdd2C+bTQ9f6vltz8bpzicJzxGCIsYtSL44InQsO/Oar9IgZu8QE4pTuunGJhVqEZru7ZN+oV+wXt51n+24SS0sNgNKVUFS74RfvsFi67CrXSWTOI8bVS0Lvv3EMWMdSF9dHGbdCFnp2/wqbW/4Qz7XYF4lcu9gLe4UtIrZ6TkAvBtnSfvTTdXj7kD6oHDjrUCjHPxdhz3BLRbj1wENZsoS3QDl22Ts7dbO8wHjutsS3/zx4DLlADoFlU8p7HJaCdrsq20P4WCeQJb6JbbLpGRAccKAidAPHMxQ4fr3b+GtjxpLJtXaytr4CPSXsCt4TloE9g5yCE6n/2UxQACp8Guh9l2MXmrD7qEGexhYqFB/OG84u3vL+gskmsKXTEqi2SiSmhvzta2p2hGCLCKRQeYbn+4TsIQfgWtYNQvC", + "AvMxAwAAA5YQMAAAABAANAAAAAoAAAACEEAAAAFMAKQAAAAmYjY0OTJkODMzNTI5ZjMxMGM1MmRjMDc3ZjBmZDgyMjcAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQC2SS2DNSnzEMUtwHfw/YInm/XLXEUMktyZTmyMWACBbEfmU6aztT3vxz6UHoCBYtKkzKrfDZLvXe0a5TRLMmK+yfl5IzIVUPdqTg6FF3Bx/GXdj4v/ZP6lAuqY5YeI4wPcKldrrIJ9DTUdhZhgdtgDtxGvrXZ8eFjcl9zM+QEykYKMwfnTCixzVOPCCo3q1lJO13NmlhVQDO+f9vvTZsYDCcZHMqlKZWcCEyY1ZpQiCqlsL8wN6tKxMuSQO8EGdH/tNzsGHwCoZq6EEL7SX/pmc2ABjpDQTLixgXwJtCpw8Fwj1xiavsFFbqSLu3SjUCcrMz9f8U5p2ROyv//lWxsXAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBksDPQ93PdZBGCEnKXcQsdB4yBA9NpImVR81JZdPmWlTwZGAXGJwt4EkBcz+xdey84JDujVtHJUzIL9Ws/Jq5MuXHr0tP5ebah1GCQF2/Ov7sctUk3UPBxeroon7gZQhuzaIJVhl0rzwWriFUbTu7H7g9eaTHMvyfUg+S0Z2p+e0+PdL5rfGOJJZ6+NJCXxxbQ//cF4s0PAzkjAuwDmC+OiUiU5V6fY4XtRMCEI7w+UCj+wQn2Wu1Wc7xVM9uow13rGaLPYkWZ/9v+wNhg0KCsVfKGhkAGGzGyKI9LAppFVTu52pBlRu9Ung7VkhF0JC2aadYKKFl99wCbsGqUYN/gtfgHYCV24LNVah2dAy8CI9UmHdWk1kIwWazbPTYKLfpYCTFxqEqXqo3ijLf0YPsfhIvCQpc5VHAvLJlDm0RFKwzK6N9Zu9s9IvJHzIpaAAHCQJPtYxPwWMdt83njGo9wu1+aVkl5Sb5X8N16AybbnQ7fCBqJruGBM0LHtWVbHEiEygD7OStzyhT5rXKZSQYMA9I2CvK1t7qfDXDM40k8SVQ5CrS9R8x1wqQbe+DqNJ9tMfbUmN0xrO/w2pTl/4edKW30TShW/fr3vCWpVq8gcm3CVFSZUaC4T9wqH96K6KgIPbmg1Hk158pxXYXopEv6ZxR7UTPxKB0O22aIHB6UQ5", + "AvMxAwAAA5YQMAAAABAANAAAAAoAAAABEEAAAAFMAKQAAAAmOTdhNTJkMThjMDBjYWE3YmZlYmQ4NTg0MDJkMzBhY2QAAAAAUl8ogFRAXAABEAAAARQwggEKAoIBAQCXpS0YwAyqe/69hYQC0wrNz7eUHAmJfR5EV7NVFQeOxtTlFwbdvRMK8ZpfqEoRhIPXAYCc9Dv3F7WcmcFer8d50EWhlK7rCQScaRdwL1UmF1dUY8bR8QxhJOUgwmrlzeKOHi2DJ3/9AXm7NJR8XMJgHEQQwi3z/aQsWrwCUA0mk68C8a3vjLtcMj5XBuNXRtGZ9zFjiI9Xt19y0iIKdYpfzOnJTKVETcjH7XPBBbJETWkrEyToHXPjcfhESAbJDOoyfQQbxHMQNE7no7owN08LoWX2kOSGtl2m6JbE2OEdJig83a6U3PDYfYM5LCfsAJEIroYhB3qZJDE98zGC8jihAgMBAAEQUAAAAjIApAAAACZlM2Y4YjY3ZjJmYjM0NzZlZmYxZmM3ZjNhNjEzM2M5OQEgAAACBiwl7oRPJzLlwDd8AzVolFQH1ZS+MWLA4B1eHCjCXSMn+zS0Su6CrpC6/vLwECaKSfNZ8y7T2fNDPJHMLmc1F6jJkdNZq3TZGNRgJx24OF3G5MU6mAH7DBsz7muFto+URTJl9CdJviIyQAn5E+R4Gp531RJdKlbqJl/gWuQMVem+eo3elpVEn8Ckg0yvFaFdhGFTOPyrXOZ6fI0pdCX0SH2q/vAIxGDRzaSYmsR0Y+oYZs0AeRnZD9iEh1v17xnVEdSoLZmZbjlLXXgqhbdXGik6ZoXQg3bTfl5D1j8Tk/d/CXqf0SUKBnIafaNgUeQSMY95M3k3vjPQN7vHdXmg19GnqQmBnGq45qdKI7+0Erfhl4po1z6yVvx9JfIMIDOsKwO3U/As5zbO2BYso0pUP4+gndissfDfqlPRni3orA0tlV6NuLmXi1wkHCu8HQ8WOqEUlWDJNLNpHW5OmgjMFqlIPt7hX5jlc9eXd4oMyaqXm1Tg8Cgbh5DYaT9A7He47+QhqYlPygqK9Fm0ZnH3Yz51cm3p2tRB1JU7qH9h5UqLLKJMBuIx7e9L5ieTfzKmTw6tqpIpHpiR/8bSQlKkw2LxikFy3OXL5obY1t9sWk35BNZQqcqflI6mkPrvGQKwN+co8GjUon5/Y1HSM6ursaJtkD8dz+oXVyWAokkuD7QZ", + + +}; + + + +EVP_PKEY *RsRecogn::loadMasterKey() +{ + /* load master signing key */ + size_t keylen; + char *keyptr; + + Radix64::decode(RecognKey, keyptr, keylen); + + const unsigned char *keyptr2 = (const unsigned char *) keyptr; + long keylen2 = keylen; + + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr2), keylen2); + delete []keyptr; + + if (!rsakey) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadMasterKeys() failed rsakey load"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return NULL; + } + + + EVP_PKEY *signKey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(signKey, rsakey); + + return signKey; +} + + +bool RsRecogn::loadSigningKeys(std::map &signMap) +{ + + EVP_PKEY *signKey = loadMasterKey(); + RsGxsRecognSerialiser recognSerialiser; + + if (!signKey) + { + std::cerr << "RsRecogn::loadSigningKeys() missing Master Key"; + return false; + } + + + time_t now = time(NULL); + + for(int i = 0; i < NUM_RECOGN_SIGN_KEYS; i++) + { + char *signerbuf; + size_t len; + Radix64::decode(RecognSigningKeys[i], signerbuf, len); + + uint32_t pktsize = len; + RsItem *pktitem = recognSerialiser.deserialise(signerbuf, &pktsize); + RsGxsRecognSignerItem *item = dynamic_cast(pktitem); + + delete []signerbuf; + + if (!item) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadSigningKeys() failed to deserialise SignerItem"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + continue; + } + +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadSigningKeys() SignerItem: "; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + + /* check dates */ + if ((item->key.startTS > (unsigned) now) || (item->key.endTS < (unsigned) now)) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadSigningKeys() failed timestamp"; + std::cerr << std::endl; + std::cerr << "RsRecogn::loadSigningKeys() key.startTS: " << item->key.startTS; + std::cerr << std::endl; + std::cerr << "RsRecogn::loadSigningKeys() now: " << now; + std::cerr << std::endl; + std::cerr << "RsRecogn::loadSigningKeys() key.endTS: " << item->key.endTS; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + delete item; + continue; + } + + /* check signature */ + RsTlvKeySignature signature = item->sign; + item->sign.TlvShallowClear(); + + unsigned int siglen = signature.signData.bin_len; + unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; + + /* store in */ + uint32_t datalen = recognSerialiser.size(item); + uint8_t *data = (uint8_t *) malloc(datalen); + uint32_t pktlen = datalen; + int signOk = 0; + + if (recognSerialiser.serialise(item, data, &pktlen)) + { + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, data, pktlen); + signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); + + EVP_MD_CTX_destroy(mdctx); + + item->sign = signature; + signature.TlvShallowClear(); + + if (signOk) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadSigningKeys() signature ok"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + std::string signerId = item->key.keyId; + signMap[signerId] = item; + } + } + + if (!signOk) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::loadSigningKeys() signature failed"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + delete item; + } + + free(data); + } + + /* clean up */ + EVP_PKEY_free(signKey); + return true; +} + + + +bool RsRecogn::validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item) +{ + if (item->sign.keyId != signer->key.keyId) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::validateTagSignature() keyId mismatch"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + const unsigned char *keyptr = (const unsigned char *) signer->key.keyData.bin_data; + long keylen = signer->key.keyData.bin_len; + + /* extract admin key */ + RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen); + if (!rsakey) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::validateTagSignature() failed extract signkey"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + /* check signature */ + RsTlvKeySignature signature = item->sign; + item->sign.TlvShallowClear(); + + unsigned int siglen = signature.signData.bin_len; + unsigned char *sigbuf = (unsigned char *) signature.signData.bin_data; + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + EVP_PKEY *signKey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(signKey, rsakey); + + + /* store in */ + RsGxsRecognSerialiser serialiser; + + uint32_t datalen = serialiser.size(item); + uint8_t *data = (uint8_t *) malloc(datalen); + int signOk = 0; + + uint32_t pktlen = datalen; + if (serialiser.serialise(item, data, &pktlen)) + { + + EVP_VerifyInit(mdctx, EVP_sha1()); + EVP_VerifyUpdate(mdctx, data, pktlen); + signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey); +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::validateTagSignature() sign_result: " << signOk; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + else + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::validateTagSignature() failed to serialise"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + } + + // Clean up. + item->sign = signature; + signature.TlvShallowClear(); + + EVP_MD_CTX_destroy(mdctx); + EVP_PKEY_free(signKey); + + free(data); + + return (signOk == 1); +} + + +bool rsa_sanity_check(RSA *rsa) +{ + std::cerr << "rsa_sanity_check()"; + std::cerr << std::endl; + + if (!rsa) + { + std::cerr << "rsa_sanity_check() RSA == NULL"; + std::cerr << std::endl; + return false; + } + + RSA *pubkey = RSAPublicKey_dup(rsa); + + std::string signId = RsRecogn::getRsaKeyId(rsa); + std::string signId2 = RsRecogn::getRsaKeyId(pubkey); + + bool ok = true; + if (signId != signId2) + { + std::cerr << "rsa_sanity_check() ERROR SignId Failure"; + std::cerr << std::endl; + ok = false; + } + + if (1 != RSA_check_key(rsa)) + { + std::cerr << "rsa_sanity_check() ERROR RSA key is not private"; + std::cerr << std::endl; + ok = false; + } + +#if 0 + if (1 == RSA_check_key(pubkey)) + { + std::cerr << "rsa_sanity_check() ERROR RSA dup key is private"; + std::cerr << std::endl; + ok = false; + } +#endif + + RSA_free(pubkey); + + if (!ok) + { + exit(1); + } + + return true; +} + + + +bool RsRecogn::signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item) +{ + RsGxsRecognSerialiser serialiser; + + RSA *rsa = EVP_PKEY_get1_RSA(signKey); + std::string signId = getRsaKeyId(rsa); + rsa_sanity_check(rsa); + RSA_free(rsa); + + item->sign.TlvClear(); + + /* write out the item for signing */ + uint32_t len = serialiser.size(item); + char *buf = new char[len]; + if (!serialiser.serialise(item, buf, &len)) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::signTag() Failed serialise TagItem:"; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + delete []buf; + return false; + } + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, buf, len); + + unsigned int siglen = EVP_PKEY_size(signKey); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); + + /* save signature */ + item->sign.signData.setBinData(sigbuf, siglen); + item->sign.keyId = signId; + + /* clean up */ + EVP_MD_CTX_destroy(mdctx); + delete []buf; + + return true; +} + +bool RsRecogn::signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item) +{ + std::cerr << "RsRecogn::signSigner()"; + std::cerr << std::endl; + + RsGxsRecognSerialiser serialiser; + + std::cerr << "RsRecogn::signSigner() Checking Key"; + std::cerr << std::endl; + + RSA *rsa = EVP_PKEY_get1_RSA(signKey); + std::string signId = getRsaKeyId(rsa); + rsa_sanity_check(rsa); + RSA_free(rsa); + + std::cerr << "RsRecogn::signSigner() Key Okay"; + std::cerr << std::endl; + + item->sign.TlvClear(); + + /* write out the item for signing */ + uint32_t len = serialiser.size(item); + char *buf = new char[len]; + if (!serialiser.serialise(item, buf, &len)) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::signSigner() Failed serialise SignerItem:"; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + delete []buf; + return false; + } + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, buf, len); + + unsigned int siglen = EVP_PKEY_size(signKey); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); + + /* save signature */ + item->sign.signData.setBinData(sigbuf, siglen); + item->sign.keyId = signId; + + /* clean up */ + EVP_MD_CTX_destroy(mdctx); + delete []buf; + + return true; +} + + +bool RsRecogn::signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item) +{ + std::cerr << "RsRecogn::signTagRequest()"; + std::cerr << std::endl; + + RsGxsRecognSerialiser serialiser; + + RSA *rsa = EVP_PKEY_get1_RSA(signKey); + std::string signId = getRsaKeyId(rsa); + rsa_sanity_check(rsa); + RSA_free(rsa); + + item->sign.TlvClear(); + + /* write out the item for signing */ + uint32_t len = serialiser.size(item); + char *buf = new char[len]; + if (!serialiser.serialise(item, buf, &len)) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::signTagRequest() Failed serialise Tag Request:"; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + delete []buf; + return false; + } + + /* calc and check signature */ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + EVP_SignInit(mdctx, EVP_sha1()); + EVP_SignUpdate(mdctx, buf, len); + + unsigned int siglen = EVP_PKEY_size(signKey); + unsigned char sigbuf[siglen]; + EVP_SignFinal(mdctx, sigbuf, &siglen, signKey); + + /* save signature */ + item->sign.signData.setBinData(sigbuf, siglen); + item->sign.keyId = signId; + + /* clean up */ + EVP_MD_CTX_destroy(mdctx); + delete []buf; + + return true; +} + + +bool RsRecogn::itemToRadix64(RsItem *item, std::string &radstr) +{ + RsGxsRecognSerialiser serialiser; + + /* write out the item for signing */ + uint32_t len = serialiser.size(item); + char *buf = new char[len]; + if (!serialiser.serialise(item, buf, &len)) + { + return false; + } + + radstr.clear(); + Radix64::encode(buf, len, radstr); + + return true; +} + + +std::string RsRecogn::getRsaKeyId(RSA *pubkey) +{ + int len = BN_num_bytes(pubkey -> n); + unsigned char tmp[len]; + BN_bn2bin(pubkey -> n, tmp); + + // copy first CERTSIGNLEN bytes... + if (len > CERTSIGNLEN) + { + len = CERTSIGNLEN; + } + + std::string id; + for(uint32_t i = 0; i < CERTSIGNLEN; i++) + { + rs_sprintf_append(id, "%02x", (uint16_t) (((uint8_t *) (tmp))[i])); + } + + return id; +} + + + +RsGxsRecognTagItem *RsRecogn::extractTag(const std::string &encoded) +{ + // Decode from Radix64 encoded Packet. + size_t buflen; + char *buffer; + uint32_t pktsize; + + Radix64::decode(encoded, buffer, buflen); + pktsize = buflen; + + RsGxsRecognSerialiser serialiser; + RsItem *item = serialiser.deserialise(buffer, &pktsize); + delete []buffer; + + if (!item) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::extractTag() ERROR Deserialise failed"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return NULL; + } + + RsGxsRecognTagItem *tagitem = dynamic_cast(item); + + if (!tagitem) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::extractTag() ERROR Not TagItem, is: "; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + delete item; + } + + return tagitem; +} + + +bool RsRecogn::createTagRequest(const RsTlvSecurityKey &key, const std::string &id, const std::string &nickname, uint16_t tag_class, uint16_t tag_type, const std::string &comment, std::string &tag) +{ + RsGxsRecognReqItem *item = new RsGxsRecognReqItem(); + + EVP_PKEY *signKey = EVP_PKEY_new(); + RSA *rsakey = GxsSecurity::extractPrivateKey(key); + if (!rsakey) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::createTagRequest() Failed to extract key"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + if (!EVP_PKEY_assign_RSA(signKey, rsakey)) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::createTagRequest() Failed to assign key"; + std::cerr << std::endl; +#endif // DEBUG_RECOGN + return false; + } + + item->issued_at = time(NULL); + item->period = 365 * 24 * 3600; + item->tag_class = tag_class; + item->tag_type = tag_type; + + item->nickname = nickname; + item->identity = id; + item->comment = comment; + + bool signOk = RsRecogn::signTagRequest(signKey,item); + EVP_PKEY_free(signKey); + + if (!signOk) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::createTagRequest() Failed to sign Tag Request:"; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + delete item; + return false; + } + + /* write out the item for signing */ + RsGxsRecognSerialiser serialiser; + uint32_t len = serialiser.size(item); + char *buf = new char[len]; + bool serOk = serialiser.serialise(item, buf, &len); + delete item; + + if (serOk) + { + Radix64::encode(buf, len, tag); + } + + delete []buf; + + if (!serOk) + { +#ifdef DEBUG_RECOGN + std::cerr << "RsRecogn::createTagRequest() Failed serialise Tag Request:"; + std::cerr << std::endl; + item->print(std::cerr); +#endif // DEBUG_RECOGN + return false; + } + + return serOk; +} + + diff --git a/libretroshare/src/util/rsrecogn.h b/libretroshare/src/util/rsrecogn.h new file mode 100644 index 000000000..a8df7f25e --- /dev/null +++ b/libretroshare/src/util/rsrecogn.h @@ -0,0 +1,61 @@ + +/* + * libretroshare/src/util: rsrecogn.h + * + * RetroShare Utilities + * + * Copyright 2013 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef RSUTIL_RECOGN_H +#define RSUTIL_RECOGN_H + +#include +#include +#include +#include + +#include "serialiser/rsgxsrecognitems.h" + +namespace RsRecogn { + +EVP_PKEY * loadMasterKey(); +bool loadSigningKeys(std::map &signMap); +bool validateTagSignature(RsGxsRecognSignerItem *signer, RsGxsRecognTagItem *item); + +bool signTag(EVP_PKEY *signKey, RsGxsRecognTagItem *item); +bool signSigner(EVP_PKEY *signKey, RsGxsRecognSignerItem *item); +bool signTagRequest(EVP_PKEY *signKey, RsGxsRecognReqItem *item); + +bool itemToRadix64(RsItem *item, std::string &radstr); + +std::string getRsaKeyId(RSA *pubkey); + +RsGxsRecognTagItem *extractTag(const std::string &encoded); + +bool createTagRequest(const RsTlvSecurityKey &key, + const std::string &id, const std::string &nickname, + uint16_t tag_class, uint16_t tag_type, + const std::string &comment, std::string &tag); + +} + +#endif