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