From 3e1b155f1a329bdba20895937e933851e2805d30 Mon Sep 17 00:00:00 2001 From: drbob Date: Fri, 8 Feb 2008 12:39:40 +0000 Subject: [PATCH] Completed Basic configuration storage: * Added read/writetofile() fns to BinMemInterface * Added SignData() fns to AuthXPGP. * Added Certificate saving to AuthXPGP. * added Signatures to Configuration. * now discards messages if Hash is wrong (p3msgservice) git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@341 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pqi/authxpgp.cc | 97 +++++++++++++++- libretroshare/src/pqi/authxpgp.h | 7 +- libretroshare/src/pqi/p3authmgr.cc | 21 ++++ libretroshare/src/pqi/p3authmgr.h | 11 +- libretroshare/src/pqi/p3cfgmgr.cc | 115 ++++++++++++++++--- libretroshare/src/pqi/p3cfgmgr.h | 5 +- libretroshare/src/pqi/pqibin.cc | 86 +++++++++++++- libretroshare/src/pqi/pqibin.h | 6 + libretroshare/src/rsserver/p3face-config.cc | 2 + libretroshare/src/rsserver/p3face-server.cc | 3 + libretroshare/src/rsserver/p3face-startup.cc | 4 +- libretroshare/src/services/p3msgservice.cc | 35 ++++-- 12 files changed, 353 insertions(+), 39 deletions(-) diff --git a/libretroshare/src/pqi/authxpgp.cc b/libretroshare/src/pqi/authxpgp.cc index 7d7c74810..2cd70a7a9 100644 --- a/libretroshare/src/pqi/authxpgp.cc +++ b/libretroshare/src/pqi/authxpgp.cc @@ -82,7 +82,7 @@ xpgpcert::xpgpcert(XPGP *xpgp, std::string pid) AuthXPGP::AuthXPGP() - :init(0), sslctx(NULL), pkey(NULL) + :init(0), sslctx(NULL), pkey(NULL), mToSaveCerts(false), mConfigSaveActive(true) { } @@ -679,6 +679,9 @@ bool AuthXPGP::TrustCertificate(std::string id, bool totrust) /* reevaluate the auth of the xpgp */ cert->trustLvl = XPGP_auth_certificate(pgp_keyring, cert->certificate); valid = true; + + /* resave if changed trust setting */ + mToSaveCerts = true; } xpgpMtx.unlock(); /**** UNLOCK ****/ @@ -755,8 +758,62 @@ bool AuthXPGP::AuthCertificate(std::string id) } - /* Sign / Encrypt / Verify Data (TODO) */ + +bool AuthXPGP::SignData(std::string input, std::string &sign) +{ + return SignData(input.c_str(), input.length(), sign); +} + +bool AuthXPGP::SignData(const void *data, const uint32_t len, std::string &sign) +{ + + RsStackMutex stack(xpgpMtx); /***** STACK LOCK MUTEX *****/ + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + unsigned int signlen = EVP_PKEY_size(pkey); + unsigned char signature[signlen]; + + if (0 == EVP_SignInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_SignInit Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignUpdate(mdctx, data, len)) + { + std::cerr << "EVP_SignUpdate Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_SignFinal(mdctx, signature, &signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + + sign.clear(); + std::ostringstream out; + out << std::hex; + for(uint32_t i = 0; i < signlen; i++) + { + out << std::setw(2) << std::setfill('0'); + out << (uint32_t) (signature[i]); + } + + sign = out.str(); + + return true; +} + /**** NEW functions we've added ****/ @@ -1119,6 +1176,8 @@ bool AuthXPGP::ProcessXPGP(XPGP *xpgp, std::string &id) cert->signers = getXPGPsigners(xpgp); + /* resave if new certificate */ + mToSaveCerts = true; xpgpMtx.unlock(); /**** UNLOCK ****/ id = xpgpid; @@ -1592,6 +1651,33 @@ int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, * */ +bool AuthXPGP::FinalSaveCertificates() +{ + CheckSaveCertificates(); + + RsStackMutex stack(xpgpMtx); /***** LOCK *****/ + mConfigSaveActive = false; + return true; +} + +bool AuthXPGP::CheckSaveCertificates() +{ + xpgpMtx.lock(); /***** LOCK *****/ + + if ((mConfigSaveActive) && (mToSaveCerts)) + { + mToSaveCerts = false; + xpgpMtx.unlock(); /**** UNLOCK ****/ + + saveCertificates(); + return true; + } + + xpgpMtx.unlock(); /**** UNLOCK ****/ + + return false; +} + bool AuthXPGP::saveCertificates() { // construct file name. @@ -1605,6 +1691,12 @@ bool AuthXPGP::saveCertificates() xpgpMtx.unlock(); /**** UNLOCK ****/ + /* add on the slash */ + if (neighdir != "") + { + neighdir += "/"; + } + std::map::iterator mit; std::string conftxt; @@ -1989,6 +2081,7 @@ bool AuthXPGP::loadCertificates(bool &oldFormat, std::map mCerts; }; diff --git a/libretroshare/src/pqi/p3authmgr.cc b/libretroshare/src/pqi/p3authmgr.cc index 10db0beaa..d104f9761 100644 --- a/libretroshare/src/pqi/p3authmgr.cc +++ b/libretroshare/src/pqi/p3authmgr.cc @@ -187,6 +187,16 @@ bool p3DummyAuthMgr::getDetails(std::string id, pqiAuthDetails &details) return false; } +bool p3DummyAuthMgr::FinalSaveCertificates() +{ + return false; +} + +bool p3DummyAuthMgr::CheckSaveCertificates() +{ + return false; +} + bool p3DummyAuthMgr::saveCertificates() { return false; @@ -248,3 +258,14 @@ bool p3DummyAuthMgr::TrustCertificate(std::string id, bool trust) return false; } +bool p3DummyAuthMgr::SignData(std::string input, std::string &sign) +{ + return false; +} + +bool p3DummyAuthMgr::SignData(const void *data, const uint32_t len, std::string &sign) +{ + return false; +} + + diff --git a/libretroshare/src/pqi/p3authmgr.h b/libretroshare/src/pqi/p3authmgr.h index e842bd309..54ebc62bc 100644 --- a/libretroshare/src/pqi/p3authmgr.h +++ b/libretroshare/src/pqi/p3authmgr.h @@ -96,6 +96,8 @@ virtual std::string getName(std::string id) = 0; virtual bool getDetails(std::string id, pqiAuthDetails &details) = 0; /* High Level Load/Save Configuration */ +virtual bool FinalSaveCertificates() = 0; +virtual bool CheckSaveCertificates() = 0; virtual bool saveCertificates() = 0; virtual bool loadCertificates() = 0; @@ -119,10 +121,11 @@ virtual bool RevokeCertificate(std::string id) = 0; virtual bool TrustCertificate(std::string id, bool trust) = 0; /* Sign / Encrypt / Verify Data (TODO) */ +virtual bool SignData(std::string input, std::string &sign) = 0; +virtual bool SignData(const void *data, const uint32_t len, std::string &sign) = 0; + //virtual bool encryptData(std::string recipientId, std::string plaindata, std::string &result); - - }; @@ -155,6 +158,8 @@ virtual std::string getName(std::string id); virtual bool getDetails(std::string id, pqiAuthDetails &details); /* High Level Load/Save Configuration */ +virtual bool FinalSaveCertificates(); +virtual bool CheckSaveCertificates(); virtual bool saveCertificates(); virtual bool loadCertificates(); @@ -173,6 +178,8 @@ virtual bool SignCertificate(std::string id); virtual bool RevokeCertificate(std::string id); virtual bool TrustCertificate(std::string id, bool trust); +virtual bool SignData(std::string input, std::string &sign); +virtual bool SignData(const void *data, const uint32_t len, std::string &sign); std::string mOwnId; std::map mPeerList; diff --git a/libretroshare/src/pqi/p3cfgmgr.cc b/libretroshare/src/pqi/p3cfgmgr.cc index 1388356cf..8f0fe1de9 100644 --- a/libretroshare/src/pqi/p3cfgmgr.cc +++ b/libretroshare/src/pqi/p3cfgmgr.cc @@ -25,6 +25,7 @@ #include "pqi/p3cfgmgr.h" +#include "pqi/p3authmgr.h" #include "pqi/pqibin.h" #include "pqi/pqistreamer.h" @@ -32,8 +33,8 @@ #define CONFIG_DEBUG 1 -p3ConfigMgr::p3ConfigMgr(std::string dir, std::string fname, std::string signame) - :basedir(dir), metafname(fname), metasigfname(signame), +p3ConfigMgr::p3ConfigMgr(p3AuthMgr *am, std::string dir, std::string fname, std::string signame) + :mAuthMgr(am), basedir(dir), metafname(fname), metasigfname(signame), mConfigSaveActive(true) { @@ -108,6 +109,12 @@ void p3ConfigMgr::saveConfiguration() std::cerr << it->first << " Hash: " << it->second->Hash(); std::cerr << std::endl; #endif + if (it->second->Hash() == "") + { + /* skip if no hash */ + continue; + } + RsTlvKeyValue kv; { std::ostringstream out; @@ -126,23 +133,47 @@ void p3ConfigMgr::saveConfiguration() #endif /* Write the data to a stream */ - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE; - BinInterface *bio = new BinFileInterface(metafname.c_str(), bioflags); + uint32_t bioflags = BIN_FLAGS_WRITEABLE; + BinMemInterface *membio = new BinMemInterface(1000, bioflags); RsSerialiser *rss = new RsSerialiser(); rss->addSerialType(new RsGeneralConfigSerialiser()); - pqistreamer stream(rss, "CONFIG", bio, 0); + pqistreamer stream(rss, "CONFIG", membio, 0); stream.SendItem(item); stream.tick(); stream.tick(); - /* get hash */ - std::string totalhash = bio->gethash(); + /* sign data */ + std::string signature; + mAuthMgr->SignData(membio->memptr(), membio->memsize(), signature); - /* sign the hash of the data */ +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::saveConfiguration() MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << signature; + std::cerr << std::endl; +#endif + + if (!membio->writetofile(metafname.c_str())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::saveConfiguration() Failed to Write MetaFile"; + std::cerr << std::endl; +#endif + } /* write signature to configuration */ + BinMemInterface *signbio = new BinMemInterface(signature.c_str(), + signature.length(), BIN_FLAGS_READABLE); + + if (!signbio->writetofile(metasigfname.c_str())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::saveConfiguration() Failed to Write MetaSignFile"; + std::cerr << std::endl; +#endif + } } @@ -156,13 +187,63 @@ void p3ConfigMgr::loadConfiguration() std::cerr << std::endl; #endif - /* Write the data to a stream */ - uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE; - BinInterface *bio = new BinFileInterface(metafname.c_str(), bioflags); + /* write signature to configuration */ + BinMemInterface *signbio = new BinMemInterface(1000, BIN_FLAGS_READABLE); + + if (!signbio->readfromfile(metasigfname.c_str())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Failed to Load MetaSignFile"; + std::cerr << std::endl; +#endif + } + + std::string oldsignature((char *) signbio->memptr(), signbio->memsize()); + delete signbio; + + BinMemInterface *membio = new BinMemInterface(1000, BIN_FLAGS_READABLE); + + if (!membio->readfromfile(metafname.c_str())) + { +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Failed to Load MetaFile"; + std::cerr << std::endl; +#endif + delete membio; + } + + /* get signature */ + std::string signature; + mAuthMgr->SignData(membio->memptr(), membio->memsize(), signature); + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() New MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << signature; + std::cerr << std::endl; +#endif + +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Orig MetaFile Signature:"; + std::cerr << std::endl; + std::cerr << oldsignature; + std::cerr << std::endl; +#endif + + if (signature != oldsignature) + { + /* Failed */ +#ifdef CONFIG_DEBUG + std::cerr << "p3ConfigMgr::loadConfiguration() Signature Check Failed"; + std::cerr << std::endl; +#endif + return; + } + + membio->fseek(0); /* go to start */ RsSerialiser *rss = new RsSerialiser(); rss->addSerialType(new RsGeneralConfigSerialiser()); - pqistreamer stream(rss, "CONFIG", bio, 0); - + pqistreamer stream(rss, "CONFIG", membio, 0); stream.tick(); stream.tick(); @@ -182,12 +263,6 @@ void p3ConfigMgr::loadConfiguration() #endif - std::string totalhash = bio->gethash(); - - /* check it TODO */ - /* sign the hash of the data */ - /* check signature with configuration */ - /* extract info from KeyValueSet */ std::list::iterator it; for(it = item->tlvkvs.pairs.begin(); it != item->tlvkvs.pairs.end(); it++) @@ -300,6 +375,8 @@ bool p3Config::loadConfiguration(std::string &loadHash) { delete (*it); } + + setHash(""); return false; } diff --git a/libretroshare/src/pqi/p3cfgmgr.h b/libretroshare/src/pqi/p3cfgmgr.h index fc49956ea..1eae01f37 100644 --- a/libretroshare/src/pqi/p3cfgmgr.h +++ b/libretroshare/src/pqi/p3cfgmgr.h @@ -64,6 +64,7 @@ const uint32_t CONFIG_TYPE_FSERVER = 0x0003; const uint32_t CONFIG_TYPE_MSGS = 0x0004; class p3ConfigMgr; +class p3AuthMgr; class pqiConfig { @@ -111,7 +112,7 @@ bool HasConfigChanged(uint16_t idx); class p3ConfigMgr { public: - p3ConfigMgr(std::string bdir, std::string fname, std::string signame); + p3ConfigMgr(p3AuthMgr *am, std::string bdir, std::string fname, std::string signame); void tick(); void saveConfiguration(); @@ -127,6 +128,8 @@ void completeConfiguration(); /* these are constants - so shouldn't need mutex */ + p3AuthMgr *mAuthMgr; + const std::string basedir; const std::string metafname; const std::string metasigfname; diff --git a/libretroshare/src/pqi/pqibin.cc b/libretroshare/src/pqi/pqibin.cc index 340cb2d13..bee44ed3a 100644 --- a/libretroshare/src/pqi/pqibin.cc +++ b/libretroshare/src/pqi/pqibin.cc @@ -35,23 +35,23 @@ BinFileInterface::BinFileInterface(const char *fname, int flags) if ((bin_flags & BIN_FLAGS_READABLE) && (bin_flags & BIN_FLAGS_WRITEABLE)) { - buf = fopen(fname, "r+"); + buf = fopen(fname, "rb+"); /* if the file don't exist */ if (!buf) { - buf = fopen(fname, "w+"); + buf = fopen(fname, "wb+"); } } else if (bin_flags & BIN_FLAGS_READABLE) { - buf = fopen(fname, "r"); + buf = fopen(fname, "rb"); } else if (bin_flags & BIN_FLAGS_WRITEABLE) { // This is enough to remove old file in Linux... // but not in windows.... (what to do) - buf = fopen(fname, "w"); + buf = fopen(fname, "wb"); fflush(buf); /* this might help windows! */ } else @@ -155,6 +155,23 @@ BinMemInterface::BinMemInterface(int defsize, int flags) } } + +BinMemInterface::BinMemInterface(const void *data, const int defsize, int flags) + :bin_flags(flags), buf(NULL), size(defsize), + recvsize(0), readloc(0), hash(NULL), bcount(0) + { + buf = malloc(defsize); + if (bin_flags & BIN_FLAGS_HASH_DATA) + { + hash = new pqihash(); + } + + /* just remove the const + * *BAD* but senddata don't change it anyway + */ + senddata((void *) data, defsize); + } + BinMemInterface::~BinMemInterface() { if (buf) @@ -174,7 +191,7 @@ int BinMemInterface::fseek(int loc) } -int BinMemInterface::senddata(void *data, int len) +int BinMemInterface::senddata(void *data, const int len) { if(recvsize + len > size) { @@ -231,6 +248,64 @@ uint64_t BinMemInterface::bytecount() return 0; } +bool BinMemInterface::writetofile(const char *fname) +{ + FILE *fd = fopen(fname, "wb"); + if (!fd) + { + return false; + } + + if (1 != fwrite(buf, recvsize, 1, fd)) + { + fclose(fd); + return false; + } + + fclose(fd); + + return true; +} + +bool BinMemInterface::readfromfile(const char *fname) +{ + FILE *fd = fopen(fname, "rb"); + if (!fd) + { + return false; + } + + /* get size */ + ::fseek(fd, 0L, SEEK_END); + int fsize = ftell(fd); + + if (fsize > size) + { + /* not enough room */ + std::cerr << "BinMemInterface::readfromfile() not enough room"; + std::cerr << std::endl; + + fclose(fd); + return false; + } + + ::fseek(fd, 0L, SEEK_SET); + if (1 != fread(buf, fsize, 1, fd)) + { + /* not enough room */ + std::cerr << "BinMemInterface::readfromfile() failed fread"; + std::cerr << std::endl; + + fclose(fd); + return false; + } + + recvsize = fsize; + readloc = 0; + fclose(fd); + + return true; +} /**************************************************************************/ @@ -448,4 +523,3 @@ std::string NetBinDummy::gethash() return std::string(""); } - diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h index 53c12db7b..52fa037ee 100644 --- a/libretroshare/src/pqi/pqibin.h +++ b/libretroshare/src/pqi/pqibin.h @@ -76,12 +76,18 @@ class BinMemInterface: public BinInterface { public: BinMemInterface(int defsize, int flags); + BinMemInterface(const void *data, const int size, int flags); virtual ~BinMemInterface(); + /* Extra Interfaces */ int fseek(int loc); int memsize() { return recvsize; } void *memptr() { return buf; } + /* file interface */ +bool writetofile(const char *fname); +bool readfromfile(const char *fname); + virtual int tick() { return 1; } virtual int senddata(void *data, int len); diff --git a/libretroshare/src/rsserver/p3face-config.cc b/libretroshare/src/rsserver/p3face-config.cc index 727702f52..c18298bb8 100644 --- a/libretroshare/src/rsserver/p3face-config.cc +++ b/libretroshare/src/rsserver/p3face-config.cc @@ -335,6 +335,8 @@ void RsServer::ConfigFinalSave() { /* force saving of transfers */ server->saveFileTransferStatus(); + + mAuthMgr->FinalSaveCertificates(); mConfigMgr->completeConfiguration(); } diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc index 433898677..2f6c1951a 100644 --- a/libretroshare/src/rsserver/p3face-server.cc +++ b/libretroshare/src/rsserver/p3face-server.cc @@ -242,6 +242,9 @@ void RsServer::run() /* force saving FileTransferStatus */ server->saveFileTransferStatus(); + + /* see if we need to resave certs */ + mAuthMgr->CheckSaveCertificates(); /* hour loop */ if (++min >= 60) diff --git a/libretroshare/src/rsserver/p3face-startup.cc b/libretroshare/src/rsserver/p3face-startup.cc index e036c7aca..95c4bcc31 100644 --- a/libretroshare/src/rsserver/p3face-startup.cc +++ b/libretroshare/src/rsserver/p3face-startup.cc @@ -498,7 +498,7 @@ int RsServer::StartupRetroShare(RsInit *config) server->setSaveDir(config->homePath.c_str()); /* Default Save Dir - config will overwrite */ server->setSearchInterface(pqih, mAuthMgr, mConnMgr); - mConfigMgr = new p3ConfigMgr(config->basedir, "rs-v0.4.cfg", "rs-v0.4.sgn"); + mConfigMgr = new p3ConfigMgr(mAuthMgr, config->basedir, "rs-v0.4.cfg", "rs-v0.4.sgn"); mGeneralConfig = new p3GeneralConfig(); @@ -551,6 +551,8 @@ int RsServer::StartupRetroShare(RsInit *config) if (oldFormat) { + std::cerr << "Startup() Loaded Old Certificate Format" << std::endl; + /* transfer all authenticated peers to friend list */ std::list authIds; mAuthMgr->getAuthenticatedList(authIds); diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index 458c9e034..bf37bef9e 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -328,20 +328,41 @@ bool p3MsgService::loadConfiguration(std::string &loadHash) std::string hashin = in->gethash(); + delete pa_in; + if (hashin != loadHash) { /* big error message! */ - std::cerr << "p3MsgService::loadConfiguration() FAILED!" << std::endl; - std::cerr << "p3MsgService::loadConfiguration() FAILED!" << std::endl; - std::cerr << "p3MsgService::loadConfiguration() FAILED!" << std::endl; - std::cerr << "p3MsgService::loadConfiguration() FAILED!" << std::endl; - std::cerr << "p3MsgService::loadConfiguration() FAILED!" << std::endl; + std::cerr << "p3MsgService::loadConfiguration() FAILED! Msgs Tampered" << std::endl; + std::string msgfileold = msgfile + ".failed"; + + rename(msgfile.c_str(), msgfileold.c_str()); + + std::cerr << "Moving Old file to: " << msgfileold << std::endl; + std::cerr << "removing dodgey msgs" << std::endl; + + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + + + std::map::iterator mit; + for(mit = imsg.begin(); mit != imsg.end(); mit++) + { + delete (mit->second); + } + imsg.clear(); + + for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) + { + delete (mit->second); + } + msgOutgoing.clear(); + setHash(""); + return false; + } setHash(hashin); - delete pa_in; - return true; }