diff --git a/src/pqi/authssl.cc b/src/pqi/authssl.cc index 565315ea37..90cb4b45cc 100644 --- a/src/pqi/authssl.cc +++ b/src/pqi/authssl.cc @@ -1312,6 +1312,14 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) return std::string(); }; + auto isStringDenied = [&](const std::string& s) -> bool { + RsStackMutex stack(sslMtx); + for(const auto& pair : mDenyList) { + if(pair.first.toStdString() == s) return true; + } + return false; + }; + using Evt_t = RsAuthSslConnectionAutenticationEvent; std::unique_ptr ev = std::unique_ptr(new Evt_t); @@ -1339,14 +1347,16 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) if(!pgpFpr.isNull()) pgpId = PGPHandler::pgpIdFromFingerprint(pgpFpr); // in the future, we drop PGP ids and keep the fingerprint all along } - + if(sslId.isNull()) { std::string errMsg = "x509Cert has invalid sslId!"; RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - if(rsEvents) + + + if(rsEvents && !isNotifyDenied(pgpId) && !isStringDenied(pgpId.toStdString())) { ev->mSslCn = sslCn; ev->mSslId = sslId; @@ -1368,7 +1378,9 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - if(rsEvents) + + + if(rsEvents && !isNotifyDenied(pgpId) && !isStringDenied(pgpId.toStdString())) { ev->mSslId = sslId; ev->mSslCn = sslCn; @@ -1426,7 +1438,9 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) RsInfo() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - if(rsEvents) + + + if(rsEvents && !isNotifyDenied(pgpId)) { ev->mSslId = sslId; ev->mSslCn = sslCn; @@ -1467,7 +1481,9 @@ int AuthSSLimpl::VerifyX509Callback(int /*preverify_ok*/, X509_STORE_CTX* ctx) Dbg1() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; - if(rsEvents) + + + if(rsEvents && !isNotifyDenied(pgpId)) { ev->mSslId = sslId; ev->mSslCn = sslCn; @@ -1874,6 +1890,18 @@ bool AuthSSLimpl::saveList(bool& cleanup, std::list& lst) } lst.push_back(vitem); + /* Save Deny List */ + if (!mDenyList.empty()) { + RsConfigKeyValueSet* denyItem = new RsConfigKeyValueSet; + for (const auto& pair : mDenyList) { + RsTlvKeyValue kv; + kv.key = pair.first.toStdString(); + kv.value = "DENY:" + pair.second; + denyItem->tlvkvs.pairs.push_back(kv); + } + lst.push_back(denyItem); + } + return true ; } @@ -1903,6 +1931,11 @@ bool AuthSSLimpl::loadList(std::list& load) continue; } + if (kit->value.compare(0, 5, "DENY:") == 0) { + mDenyList[RsPgpId(kit->key)] = kit->value.substr(5); + continue; + } + X509 *peer = loadX509FromPEM(kit->value); /* authenticate it */ uint32_t diagnos ; @@ -1918,6 +1951,8 @@ bool AuthSSLimpl::loadList(std::list& load) return true; } + + const EVP_PKEY*RsX509Cert::getPubKey(const X509& x509) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) @@ -1926,3 +1961,37 @@ const EVP_PKEY*RsX509Cert::getPubKey(const X509& x509) return X509_get0_pubkey(&x509); #endif } + +void AuthSSLimpl::addNotifyDeny(const RsPgpId& pgpId, const std::string& name) +{ + RsStackMutex stack(sslMtx); + mDenyList[pgpId] = name; + IndicateConfigChanged(); +} + +void AuthSSLimpl::removeNotifyDeny(const RsPgpId& pgpId) +{ + RsStackMutex stack(sslMtx); + mDenyList.erase(pgpId); + IndicateConfigChanged(); +} + +bool AuthSSLimpl::isNotifyDenied(const RsPgpId& pgpId) +{ + RsStackMutex stack(sslMtx); + if(mDenyList.find(pgpId) != mDenyList.end()) return true; + + if(pgpId.isNull()) { + std::string s = pgpId.toStdString(); + for(const auto& pair : mDenyList) { + if(pair.first.toStdString() == s) return true; + } + } + return false; +} + +void AuthSSLimpl::getNotifyDenyList(std::map& ids) +{ + RsStackMutex stack(sslMtx); + ids = mDenyList; +} diff --git a/src/pqi/authssl.h b/src/pqi/authssl.h index 1184018764..86ff05483c 100644 --- a/src/pqi/authssl.h +++ b/src/pqi/authssl.h @@ -112,6 +112,11 @@ class AuthSSL virtual X509* SignX509ReqWithGPG(X509_REQ* req, long days) = 0; + virtual void addNotifyDeny(const RsPgpId& pgpId, const std::string& name) = 0; + virtual void removeNotifyDeny(const RsPgpId& pgpId) = 0; + virtual bool isNotifyDenied(const RsPgpId& pgpId) = 0; + virtual void getNotifyDenyList(std::map& ids) = 0; + /** * @brief Verify PGP signature correcteness on given X509 certificate * Beware this doesn't check if the PGP signer is friend or not, just if the @@ -207,6 +212,11 @@ class AuthSSLimpl : public AuthSSL, public p3Config bool decrypt(void *&out, int &outlen, const void *in, int inlen) override; virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) override; + + void addNotifyDeny(const RsPgpId& pgpId, const std::string& name) override; + void removeNotifyDeny(const RsPgpId& pgpId) override; + bool isNotifyDenied(const RsPgpId& pgpId) override; + void getNotifyDenyList(std::map& ids) override; /// @see AuthSSL bool AuthX509WithGPG(X509 *x509, bool verbose, uint32_t& auth_diagnostic) override; @@ -265,4 +275,6 @@ class AuthSSLimpl : public AuthSSL, public p3Config RsPgpId _last_gpgid_to_connect; std::string _last_sslcn_to_connect; RsPeerId _last_sslid_to_connect; + + std::map mDenyList; }; diff --git a/src/pqi/pqissllistener.cc b/src/pqi/pqissllistener.cc index 7e027c5a98..0692bb1101 100644 --- a/src/pqi/pqissllistener.cc +++ b/src/pqi/pqissllistener.cc @@ -493,10 +493,33 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool if(vres == X509_V_OK && nullptr != rsEvents) { - auto ev = std::make_shared(); - ev->mLocator = RsUrl(incoming_connexion_info.addr); - ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; - rsEvents->postEvent(ev); + // Check if denied before posting event + bool denied = false; + X509 *x509_check = SSL_get_peer_certificate(incoming_connexion_info.ssl); + RsPgpId checkedPgpId; // Default 0 + if(x509_check) { + checkedPgpId = RsX509Cert::getCertIssuer(*x509_check); + X509_free(x509_check); + } + + if(AuthSSL::instance().isNotifyDenied(checkedPgpId)) { + denied = true; + } + + if(!denied) { + auto ev = std::make_shared(); + ev->mLocator = RsUrl(incoming_connexion_info.addr); + // Try to fill in more info if available + if((x509_check = SSL_get_peer_certificate(incoming_connexion_info.ssl))) { + ev->mPgpId = RsX509Cert::getCertIssuer(*x509_check); + ev->mSslId = RsX509Cert::getCertSslId(*x509_check); + ev->mSslCn = RsX509Cert::getCertName(*x509_check); + X509_free(x509_check); + } + + ev->mErrorCode = RsAuthSslError::MISSING_AUTHENTICATION_INFO; + rsEvents->postEvent(ev); + } } closeConnection(fd, incoming_connexion_info.ssl); diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 1629eb3c8c..44dd0e3af9 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -1757,6 +1757,7 @@ int RsServer::StartupRetroShare() mConfigMgr->addConfiguration("gxsnettunnel.cfg", mGxsNetTunnel); mConfigMgr->addConfiguration("peers.cfg" , mPeerMgr); mConfigMgr->addConfiguration("general.cfg" , mGeneralConfig); + mConfigMgr->addConfiguration("authssl.cfg" , dynamic_cast(&AuthSSL::instance())); mConfigMgr->addConfiguration("msgs.cfg" , msgSrv); mConfigMgr->addConfiguration("chat.cfg" , chatSrv); mConfigMgr->addConfiguration("p3History.cfg" , mHistoryMgr);