mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 16:39:29 -05:00
Cleanup huge amount of AuthSSL cruft
Make reduntant auth check in pqi effective (even if redundant only siganture was checked but friendess wasn't) Evidence redundant auth check in pqi by putting it inside #ifdef this way the beaviior being the same with and without redundat check can be verified easier Solve lot of compiler warnings and made code more readable Remove dangerous sslcert wrapper Remove misleading messeges and notification about peer not giving cert, FailedCertificate logic is wrong since many years as authentication is fully handled inside VerifyX509Callback
This commit is contained in:
parent
8300e65cad
commit
41d4599fe3
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,8 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2008 by Robert Fernie, Retroshare Team. *
|
||||
* Copyright (C) 2004-2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -19,21 +20,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef MRK_AUTH_SSL_HEADER
|
||||
#define MRK_AUTH_SSL_HEADER
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* This is an implementation of SSL certificate authentication, which is
|
||||
* overloaded with pgp style signatures, and web-of-trust authentication.
|
||||
*
|
||||
* only the owner ssl cert is store, the rest is jeus callback verification
|
||||
*
|
||||
* To use as an SSL authentication system, you must use a common CA certificate.
|
||||
* * The pqissl stuff doesn't need to differentiate between SSL, SSL + PGP,
|
||||
* as its X509 certs.
|
||||
* * The rsserver stuff has to distinguish between all three types ;(
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
@ -42,197 +30,248 @@
|
||||
#include <map>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
#include "pqi/pqi_base.h"
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/p3cfgmgr.h"
|
||||
#include "util/rsmemory.h"
|
||||
#include "retroshare/rsevents.h"
|
||||
|
||||
/* This #define removes Connection Manager references in AuthSSL.
|
||||
* They should not be here. What about Objects and orthogonality?
|
||||
* This code is also stopping immediate reconnections from working.
|
||||
/**
|
||||
* Functions to interact elegantly with X509 certificates, using this functions
|
||||
* you can avoid annoying #ifdef *SSL_VERSION_NUMBER all around the code.
|
||||
* Function names should be self descriptive.
|
||||
*/
|
||||
|
||||
class AuthSSL;
|
||||
|
||||
class sslcert
|
||||
namespace RsX509Cert
|
||||
{
|
||||
public:
|
||||
sslcert(X509* x509, const RsPeerId& id);
|
||||
sslcert();
|
||||
|
||||
/* certificate parameters */
|
||||
RsPeerId id;
|
||||
std::string name;
|
||||
std::string location;
|
||||
std::string org;
|
||||
std::string email;
|
||||
|
||||
RsPgpId issuer;
|
||||
PGPFingerprintType fpr;
|
||||
|
||||
/* Auth settings */
|
||||
bool authed;
|
||||
|
||||
/* INTERNAL Parameters */
|
||||
X509* certificate;
|
||||
std::string getCertName(const X509& x509);
|
||||
std::string getCertLocation(const X509& x509);
|
||||
std::string getCertOrg(const X509& x509);
|
||||
RsPgpId getCertIssuer(const X509& x509);
|
||||
std::string getCertIssuerString(const X509& x509);
|
||||
RsPeerId getCertSslId(const X509& x509);
|
||||
const EVP_PKEY* getPubKey(const X509& x509);
|
||||
};
|
||||
|
||||
/* required to install instance */
|
||||
/**
|
||||
* Event triggered by AuthSSL when authentication of a connection attempt either
|
||||
* fail or success
|
||||
*/
|
||||
struct RsAuthSslConnectionAutenticationEvent : RsEvent
|
||||
{
|
||||
RsAuthSslConnectionAutenticationEvent();
|
||||
|
||||
bool mSuccess;
|
||||
RsPeerId mSslId;
|
||||
std::string mSslCn;
|
||||
RsPgpId mPgpId;
|
||||
std::string mErrorMsg;
|
||||
|
||||
///* @see RsEvent @see RsSerializable
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx) override
|
||||
{
|
||||
RsEvent::serial_process(j, ctx);
|
||||
RS_SERIAL_PROCESS(mSuccess);
|
||||
RS_SERIAL_PROCESS(mSslId);
|
||||
RS_SERIAL_PROCESS(mSslCn);
|
||||
RS_SERIAL_PROCESS(mPgpId);
|
||||
RS_SERIAL_PROCESS(mErrorMsg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is an implementation of SSL certificate authentication with PGP
|
||||
* signatures, instead of centralized certification authority.
|
||||
*/
|
||||
class AuthSSL
|
||||
{
|
||||
public:
|
||||
AuthSSL();
|
||||
public:
|
||||
static AuthSSL& instance();
|
||||
|
||||
static AuthSSL *getAuthSSL();
|
||||
static void AuthSSLInit();
|
||||
RS_DEPRECATED_FOR(AuthSSL::instance())
|
||||
static AuthSSL* getAuthSSL();
|
||||
|
||||
/* Initialisation Functions (Unique) */
|
||||
virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) = 0;
|
||||
/* Initialisation Functions (Unique) */
|
||||
virtual bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) = 0;
|
||||
|
||||
virtual bool active() = 0;
|
||||
virtual int InitAuth(const char *srvr_cert, const char *priv_key,
|
||||
const char *passwd, std::string alternative_location_name) = 0;
|
||||
virtual bool CloseAuth() = 0;
|
||||
virtual bool active() = 0;
|
||||
virtual int InitAuth(
|
||||
const char* srvr_cert, const char* priv_key, const char* passwd,
|
||||
std::string alternative_location_name ) = 0;
|
||||
virtual bool CloseAuth() = 0;
|
||||
|
||||
/*********** Overloaded Functions from p3AuthMgr **********/
|
||||
|
||||
/* get Certificate Id */
|
||||
virtual const RsPeerId& OwnId() = 0;
|
||||
virtual std::string getOwnLocation() = 0;
|
||||
|
||||
/* get Certificate Id */
|
||||
virtual const RsPeerId& OwnId() = 0;
|
||||
virtual std::string getOwnLocation() = 0;
|
||||
|
||||
/* Load/Save certificates */
|
||||
virtual std::string SaveOwnCertificateToString() = 0;
|
||||
|
||||
virtual std::string SaveOwnCertificateToString() = 0;
|
||||
|
||||
/* Sign / Encrypt / Verify Data */
|
||||
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 SignData(std::string input, std::string &sign) = 0;
|
||||
virtual bool SignData(
|
||||
const void* data, const uint32_t len, std::string& sign ) = 0;
|
||||
|
||||
virtual bool SignDataBin(std::string, unsigned char*, unsigned int*) = 0;
|
||||
virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*) = 0;
|
||||
virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int) = 0;
|
||||
virtual bool VerifySignBin(const void *data, const uint32_t len,
|
||||
unsigned char *sign, unsigned int signlen, const RsPeerId& sslId) = 0;
|
||||
virtual bool SignDataBin(std::string, unsigned char*, unsigned int*) = 0;
|
||||
virtual bool SignDataBin(
|
||||
const void*, uint32_t, unsigned char*, unsigned int* ) = 0;
|
||||
virtual bool VerifyOwnSignBin(
|
||||
const void*, uint32_t, unsigned char*, unsigned int ) = 0;
|
||||
virtual bool VerifySignBin(
|
||||
const void* data, const uint32_t len, unsigned char* sign,
|
||||
unsigned int signlen, const RsPeerId& sslId ) = 0;
|
||||
|
||||
// return : false if encrypt failed
|
||||
virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, const RsPeerId& peerId) = 0;
|
||||
// return : false if decrypt fails
|
||||
virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen) = 0;
|
||||
/// return false if failed
|
||||
virtual bool encrypt(
|
||||
void*& out, int& outlen, const void* in, int inlen,
|
||||
const RsPeerId& peerId ) = 0;
|
||||
/// return false if failed
|
||||
virtual bool decrypt(void*& out, int& outlen, const void* in, int inlen) = 0;
|
||||
|
||||
virtual X509* SignX509ReqWithGPG(X509_REQ* req, long days) = 0;
|
||||
|
||||
virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) = 0;
|
||||
virtual bool AuthX509WithGPG(X509 *x509,uint32_t& auth_diagnostic)=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
|
||||
* signature is valid!
|
||||
* @param[in] x509 pointer ti the X509 certificate to check
|
||||
* @param[out] diagnostic one of RS_SSL_HANDSHAKE_DIAGNOSTIC_* diagnostic
|
||||
* codes
|
||||
* @return true if correctly signed, false otherwise
|
||||
*/
|
||||
virtual bool AuthX509WithGPG(
|
||||
X509* x509,
|
||||
uint32_t& diagnostic = RS_DEFAULT_STORAGE_PARAM(uint32_t)
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Callback provided to OpenSSL to authenticate connections
|
||||
* This is the ultimate place where connection attempts get accepted
|
||||
* if authenticated or refused if not authenticated.
|
||||
* Emits @see RsAuthSslConnectionAutenticationEvent.
|
||||
* @param preverify_ok passed by OpenSSL ignored as this call is the first
|
||||
* in the authentication callback chain
|
||||
* @param ctx OpenSSL connection context
|
||||
* @return 0 if authentication failed, 1 if success see OpenSSL
|
||||
* documentation
|
||||
*/
|
||||
virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX* ctx) = 0;
|
||||
|
||||
virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) = 0;
|
||||
virtual bool ValidateCertificate(X509 *x509, RsPeerId& peerId) = 0; /* validate + get id */
|
||||
/// SSL specific functions used in pqissl/pqissllistener
|
||||
virtual SSL_CTX* getCTX() = 0;
|
||||
|
||||
public: /* SSL specific functions used in pqissl/pqissllistener */
|
||||
virtual SSL_CTX *getCTX() = 0;
|
||||
virtual void setCurrentConnectionAttemptInfo(
|
||||
const RsPgpId& gpg_id, const RsPeerId& ssl_id,
|
||||
const std::string& ssl_cn ) = 0;
|
||||
virtual void getCurrentConnectionAttemptInfo(
|
||||
RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn ) = 0;
|
||||
|
||||
/* Restored these functions: */
|
||||
virtual void setCurrentConnectionAttemptInfo(const RsPgpId& gpg_id,const RsPeerId& ssl_id,const std::string& ssl_cn) = 0 ;
|
||||
virtual void getCurrentConnectionAttemptInfo( RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn) = 0 ;
|
||||
virtual ~AuthSSL();
|
||||
|
||||
virtual bool FailedCertificate(X509 *x509, const RsPgpId& gpgid,const RsPeerId& sslid,const std::string& sslcn,const struct sockaddr_storage &addr, bool incoming) = 0; /* store for discovery */
|
||||
virtual bool CheckCertificate(const RsPeerId& peerId, X509 *x509) = 0; /* check that they are exact match */
|
||||
protected:
|
||||
AuthSSL() {}
|
||||
|
||||
static void setAuthSSL_debug(AuthSSL*) ; // used for debug only. The real function is InitSSL()
|
||||
static AuthSSL *instance_ssl ;
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||||
};
|
||||
|
||||
|
||||
class AuthSSLimpl : public AuthSSL, public p3Config
|
||||
{
|
||||
public:
|
||||
public:
|
||||
|
||||
/* Initialisation Functions (Unique) */
|
||||
/** Initialisation Functions (Unique) */
|
||||
AuthSSLimpl();
|
||||
bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey);
|
||||
bool validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) override;
|
||||
|
||||
virtual bool active();
|
||||
virtual int InitAuth(const char *srvr_cert, const char *priv_key,
|
||||
const char *passwd, std::string alternative_location_name);
|
||||
virtual bool CloseAuth();
|
||||
bool active() override;
|
||||
int InitAuth( const char *srvr_cert, const char *priv_key,
|
||||
const char *passwd, std::string alternative_location_name )
|
||||
override;
|
||||
|
||||
bool CloseAuth() override;
|
||||
|
||||
/*********** Overloaded Functions from p3AuthMgr **********/
|
||||
|
||||
/* get Certificate Id */
|
||||
virtual const RsPeerId& OwnId();
|
||||
virtual std::string getOwnLocation();
|
||||
|
||||
const RsPeerId& OwnId() override;
|
||||
virtual std::string getOwnLocation() override;
|
||||
|
||||
/* Load/Save certificates */
|
||||
virtual std::string SaveOwnCertificateToString();
|
||||
|
||||
virtual std::string SaveOwnCertificateToString() override;
|
||||
|
||||
/* Sign / Encrypt / Verify Data */
|
||||
virtual bool SignData(std::string input, std::string &sign);
|
||||
virtual bool SignData(const void *data, const uint32_t len, std::string &sign);
|
||||
bool SignData(std::string input, std::string &sign) override;
|
||||
bool SignData(
|
||||
const void *data, const uint32_t len, std::string &sign) override;
|
||||
|
||||
virtual bool SignDataBin(std::string, unsigned char*, unsigned int*);
|
||||
virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*);
|
||||
virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int);
|
||||
virtual bool VerifySignBin(const void *data, const uint32_t len,
|
||||
unsigned char *sign, unsigned int signlen, const RsPeerId& sslId);
|
||||
bool SignDataBin(std::string, unsigned char*, unsigned int*) override;
|
||||
virtual bool SignDataBin(
|
||||
const void*, uint32_t, unsigned char*, unsigned int*) override;
|
||||
bool VerifyOwnSignBin(
|
||||
const void*, uint32_t, unsigned char*, unsigned int) override;
|
||||
virtual bool VerifySignBin(
|
||||
const void *data, const uint32_t len, unsigned char *sign,
|
||||
unsigned int signlen, const RsPeerId& sslId) override;
|
||||
|
||||
// return : false if encrypt failed
|
||||
virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, const RsPeerId& peerId);
|
||||
// return : false if decrypt fails
|
||||
virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen);
|
||||
bool encrypt(
|
||||
void*& out, int& outlen, const void* in, int inlen,
|
||||
const RsPeerId& peerId ) override;
|
||||
bool decrypt(void *&out, int &outlen, const void *in, int inlen) override;
|
||||
|
||||
virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days) override;
|
||||
|
||||
virtual X509* SignX509ReqWithGPG(X509_REQ *req, long days);
|
||||
virtual bool AuthX509WithGPG(X509 *x509,uint32_t& auth_diagnostic);
|
||||
/// @see AuthSSL
|
||||
bool AuthX509WithGPG(X509 *x509,uint32_t& auth_diagnostic) override;
|
||||
|
||||
|
||||
virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx);
|
||||
virtual bool ValidateCertificate(X509 *x509, RsPeerId& peerId); /* validate + get id */
|
||||
/// @see AuthSSL
|
||||
int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) override;
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/*********************** p3config ******************************/
|
||||
/* Key Functions to be overloaded for Full Configuration */
|
||||
virtual RsSerialiser *setupSerialiser();
|
||||
virtual bool saveList(bool &cleanup, std::list<RsItem *>& );
|
||||
virtual bool loadList(std::list<RsItem *>& load);
|
||||
/* Key Functions to be overloaded for Full Configuration */
|
||||
RsSerialiser* setupSerialiser() override;
|
||||
bool saveList(bool &cleanup, std::list<RsItem *>& ) override;
|
||||
bool loadList(std::list<RsItem *>& load) override;
|
||||
/*****************************************************************/
|
||||
|
||||
public: /* SSL specific functions used in pqissl/pqissllistener */
|
||||
virtual SSL_CTX *getCTX();
|
||||
public:
|
||||
/* SSL specific functions used in pqissl/pqissllistener */
|
||||
SSL_CTX* getCTX() override;
|
||||
|
||||
/* Restored these functions: */
|
||||
virtual void setCurrentConnectionAttemptInfo(const RsPgpId& gpg_id,const RsPeerId& ssl_id,const std::string& ssl_cn) ;
|
||||
virtual void getCurrentConnectionAttemptInfo( RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn) ;
|
||||
virtual bool FailedCertificate(X509 *x509, const RsPgpId& gpgid,const RsPeerId& sslid,const std::string& sslcn,const struct sockaddr_storage &addr, bool incoming); /* store for discovery */
|
||||
virtual bool CheckCertificate(const RsPeerId& peerId, X509 *x509); /* check that they are exact match */
|
||||
/* Restored these functions: */
|
||||
void setCurrentConnectionAttemptInfo(
|
||||
const RsPgpId& gpg_id, const RsPeerId& ssl_id,
|
||||
const std::string& ssl_cn ) override;
|
||||
void getCurrentConnectionAttemptInfo(
|
||||
RsPgpId& gpg_id, RsPeerId& ssl_id, std::string& ssl_cn ) override;
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
bool LocalStoreCert(X509* x509);
|
||||
bool RemoveX509(const RsPeerId id);
|
||||
bool LocalStoreCert(X509* x509);
|
||||
bool RemoveX509(const RsPeerId id);
|
||||
|
||||
/*********** LOCKED Functions ******/
|
||||
bool locked_FindCert(const RsPeerId& id, sslcert **cert);
|
||||
bool locked_FindCert(const RsPeerId& id, X509** cert);
|
||||
|
||||
/* Data */
|
||||
/* these variables are constants -> don't need to protect */
|
||||
SSL_CTX *sslctx;
|
||||
RsPeerId mOwnId;
|
||||
sslcert *mOwnCert;
|
||||
X509* mOwnCert;
|
||||
|
||||
RsMutex sslMtx; /* protects all below */
|
||||
RsMutex sslMtx; /* protects all below */
|
||||
|
||||
|
||||
EVP_PKEY *mOwnPrivateKey;
|
||||
EVP_PKEY *mOwnPublicKey;
|
||||
EVP_PKEY* mOwnPrivateKey;
|
||||
EVP_PKEY* mOwnPublicKey;
|
||||
|
||||
int init;
|
||||
std::map<RsPeerId, X509*> mCerts;
|
||||
|
||||
std::map<RsPeerId, sslcert *> mCerts;
|
||||
|
||||
RsPgpId _last_gpgid_to_connect ;
|
||||
std::string _last_sslcn_to_connect ;
|
||||
RsPeerId _last_sslid_to_connect ;
|
||||
RsPgpId _last_gpgid_to_connect;
|
||||
std::string _last_sslcn_to_connect;
|
||||
RsPeerId _last_sslid_to_connect;
|
||||
};
|
||||
|
||||
#endif // MRK_AUTH_SSL_HEADER
|
||||
|
@ -1032,47 +1032,6 @@ bool p3LinkMgrIMPL::connectResult(const RsPeerId &id, bool success, bool isIncom
|
||||
* From various sources
|
||||
*/
|
||||
|
||||
// from pqissl, when a connection failed due to security
|
||||
void p3LinkMgrIMPL::notifyDeniedConnection(const RsPgpId& gpgid,const RsPeerId& sslid,const std::string& sslcn,const struct sockaddr_storage &/*addr*/, bool incoming)
|
||||
{
|
||||
std::cerr << "p3LinkMgrIMPL::notifyDeniedConnection()";
|
||||
std::cerr << " pgpid: " << gpgid;
|
||||
std::cerr << " sslid: " << sslid;
|
||||
std::cerr << " sslcn: " << sslcn;
|
||||
std::cerr << std::endl;
|
||||
|
||||
RsStackMutex stack(mLinkMtx); /****** STACK LOCK MUTEX *******/
|
||||
|
||||
std::map<RsPeerId, peerConnectState>::iterator it;
|
||||
it = mFriendList.find(sslid);
|
||||
if (it == mFriendList.end())
|
||||
{
|
||||
std::cerr << "p3LinkMgrIMPL::notifyDeniedConnection() of NON-FRIEND: " << sslid;
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
it->second.wasDeniedConnection = true;
|
||||
it->second.deniedTS = time(NULL);
|
||||
|
||||
if ((!incoming) && it->second.inConnAttempt)
|
||||
{
|
||||
it->second.deniedInConnAttempt = true;
|
||||
it->second.deniedConnectionAttempt = it->second.currentConnAddrAttempt;
|
||||
|
||||
std::cerr << "p3LinkMgrIMPL::notifyDeniedConnection() Denied In Connection Attempt";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.deniedInConnAttempt = false;
|
||||
std::cerr << "p3LinkMgrIMPL::notifyDeniedConnection() Denied NOT In Connection Attempt";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void p3LinkMgrIMPL::peerStatus(const RsPeerId& id, const pqiIpAddrSet &addrs,
|
||||
uint32_t type, uint32_t flags, uint32_t source)
|
||||
{
|
||||
|
@ -171,8 +171,6 @@ virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr,
|
||||
virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address) = 0;
|
||||
virtual bool retryConnect(const RsPeerId &id) = 0;
|
||||
|
||||
virtual void notifyDeniedConnection(const RsPgpId& gpgid,const RsPeerId& sslid,const std::string& sslcn,const struct sockaddr_storage &addr, bool incoming) = 0;
|
||||
|
||||
/* Network Addresses */
|
||||
virtual bool setLocalAddress(const struct sockaddr_storage &addr) = 0;
|
||||
virtual bool getLocalAddress(struct sockaddr_storage &addr) = 0;
|
||||
@ -230,8 +228,6 @@ virtual bool connectAttempt(const RsPeerId &id, struct sockaddr_storage &raddr,
|
||||
virtual bool connectResult(const RsPeerId &id, bool success, bool isIncomingConnection, uint32_t flags, const struct sockaddr_storage &remote_peer_address);
|
||||
virtual bool retryConnect(const RsPeerId &id);
|
||||
|
||||
virtual void notifyDeniedConnection(const RsPgpId& gpgid,const RsPeerId& sslid,const std::string& sslcn,const struct sockaddr_storage &addr, bool incoming);
|
||||
|
||||
/* Network Addresses */
|
||||
virtual bool setLocalAddress(const struct sockaddr_storage &addr);
|
||||
virtual bool getLocalAddress(struct sockaddr_storage &addr);
|
||||
|
@ -1115,9 +1115,6 @@ int pqissl::SSL_Connection_Complete()
|
||||
|
||||
rslog(RSL_WARNING, pqisslzone, out);
|
||||
|
||||
// attempt real error.
|
||||
Extract_Failed_SSL_Certificate();
|
||||
|
||||
rslog(RSL_ALERT, pqisslzone, "pqissl::SSL_Connection_Complete() -> calling reset()");
|
||||
reset_locked();
|
||||
waiting = WAITING_FAIL_INTERFACE;
|
||||
@ -1132,159 +1129,87 @@ int pqissl::SSL_Connection_Complete()
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pqissl::Extract_Failed_SSL_Certificate()
|
||||
{
|
||||
std::cerr << "pqissl::Extract_Failed_SSL_Certificate() FAILED Connection due to Security Issues";
|
||||
std::cerr << std::endl;
|
||||
|
||||
#ifdef PQISSL_LOG_DEBUG
|
||||
rslog(RSL_DEBUG_BASIC, pqisslzone,
|
||||
"pqissl::Extract_Failed_SSL_Certificate()");
|
||||
#endif
|
||||
|
||||
// Get the Peer Certificate....
|
||||
X509 *peercert = SSL_get_peer_certificate(ssl_connection);
|
||||
|
||||
if (peercert == NULL)
|
||||
{
|
||||
rslog(RSL_WARNING, pqisslzone,
|
||||
"pqissl::Extract_Failed_SSL_Certificate() Peer Didnt Give Cert");
|
||||
|
||||
std::cerr << "pqissl::Extract_Failed_SSL_Certificate() ERROR Peer Didn't Give Us Certificate";
|
||||
std::cerr << std::endl;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PQISSL_LOG_DEBUG
|
||||
rslog(RSL_DEBUG_BASIC, pqisslzone,
|
||||
"pqissl::Extract_Failed_SSL_Certificate() Have Peer Cert - Registering");
|
||||
#endif
|
||||
|
||||
std::cerr << "pqissl::Extract_Failed_SSL_Certificate() Passing FAILED Cert to AuthSSL for analysis";
|
||||
std::cerr << std::endl;
|
||||
|
||||
// save certificate... (and ip locations)
|
||||
// false for outgoing....
|
||||
// we actually connected to remote_addr,
|
||||
// which could be
|
||||
// (pqissl's case) sslcert->serveraddr or sslcert->localaddr.
|
||||
|
||||
RsPeerId sslid ;
|
||||
getX509id(peercert, sslid) ;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
RsPgpId gpgid(getX509CNString(peercert->cert_info->issuer));
|
||||
std::string sslcn = getX509CNString(peercert->cert_info->subject);
|
||||
#else
|
||||
RsPgpId gpgid(getX509CNString(X509_get_issuer_name(peercert)));
|
||||
std::string sslcn = getX509CNString(X509_get_subject_name(peercert));
|
||||
#endif
|
||||
|
||||
AuthSSL::getAuthSSL()->FailedCertificate(peercert, gpgid,sslid,sslcn,remote_addr, false);
|
||||
mLinkMgr->notifyDeniedConnection(gpgid, sslid, sslcn, remote_addr, false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pqissl::Authorise_SSL_Connection()
|
||||
{
|
||||
#ifdef PQISSL_DEBUG
|
||||
std::cerr << __PRETTY_FUNCTION__ << std::endl;
|
||||
#endif
|
||||
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
if (time(NULL) > ssl_connect_timeout)
|
||||
constexpr int failure = -1;
|
||||
|
||||
if (time(nullptr) > ssl_connect_timeout)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Connection timed out reset!"
|
||||
<< std::endl;
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " Connection timed out reset!"
|
||||
<< std::endl;
|
||||
reset_locked();
|
||||
}
|
||||
|
||||
int err;
|
||||
if (0 >= (err = SSL_Connection_Complete())) return err;
|
||||
|
||||
#ifdef PQISSL_LOG_DEBUG
|
||||
rslog(RSL_DEBUG_BASIC, pqisslzone,
|
||||
"pqissl::Authorise_SSL_Connection() SSL_Connection_Complete");
|
||||
#endif
|
||||
Dbg3() << __PRETTY_FUNCTION__ << "SSL_Connection_Complete success."
|
||||
<< std::endl;
|
||||
|
||||
// reset switch.
|
||||
waiting = WAITING_NOT;
|
||||
|
||||
X509 *peercert = SSL_get_peer_certificate(ssl_connection);
|
||||
|
||||
if (peercert == NULL)
|
||||
X509* peercert = SSL_get_peer_certificate(ssl_connection);
|
||||
if (!peercert)
|
||||
{
|
||||
rslog(RSL_WARNING, pqisslzone,
|
||||
"pqissl::Authorise_SSL_Connection() Peer Didnt Give Cert");
|
||||
|
||||
rslog(RSL_ALERT, pqisslzone, "pqissl::Authorise_Connection_Complete() -> calling reset()");
|
||||
// Failed completely
|
||||
reset_locked();
|
||||
return -1;
|
||||
RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer "
|
||||
<< "certificate at this point this should never happen!"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
|
||||
RsPeerId certPeerId;
|
||||
getX509id(peercert, certPeerId);
|
||||
if (RsPeerId(certPeerId) != PeerId()) {
|
||||
rslog(RSL_WARNING, pqisslzone,
|
||||
"pqissl::Authorise_SSL_Connection() the cert Id doesn't match the Peer id we're trying to connect to.");
|
||||
|
||||
rslog(RSL_ALERT, pqisslzone, "pqissl::Authorise_Connection_Complete() -> calling reset()");
|
||||
// Failed completely
|
||||
reset_locked();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef PQISSL_LOG_DEBUG
|
||||
rslog(RSL_DEBUG_BASIC, pqisslzone,
|
||||
"pqissl::Authorise_SSL_Connection() Have Peer Cert");
|
||||
#endif
|
||||
|
||||
// save certificate... (and ip locations)
|
||||
// false for outgoing....
|
||||
// we actually connected to remote_addr,
|
||||
// which could be
|
||||
// (pqissl's case) sslcert->serveraddr or sslcert->localaddr.
|
||||
|
||||
AuthSSL::getAuthSSL()->CheckCertificate(PeerId(), peercert);
|
||||
bool certCorrect = true; /* WE know it okay already! */
|
||||
|
||||
uint32_t check_result ;
|
||||
uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST;
|
||||
if (rsPeers->servicePermissionFlags(PeerId()) & RS_NODE_PERM_REQUIRE_WL)
|
||||
checking_flags |= RSBANLIST_CHECKING_FLAGS_WHITELIST;
|
||||
|
||||
if(rsBanList!=NULL && !rsBanList->isAddressAccepted(remote_addr,checking_flags,&check_result))
|
||||
{
|
||||
std::cerr << "(SS) refusing connection attempt from IP address " << sockaddr_storage_iptostring(remote_addr) << ". Reason: " <<
|
||||
((check_result == RSBANLIST_CHECK_RESULT_NOT_WHITELISTED)?"not whitelisted (peer requires whitelist)":"blacklisted") << std::endl;
|
||||
|
||||
RsServer::notify()->AddFeedItem(RS_FEED_ITEM_SEC_IP_BLACKLISTED, PeerId().toStdString(), sockaddr_storage_iptostring(remote_addr), "", "", check_result);
|
||||
reset_locked();
|
||||
return 0 ;
|
||||
}
|
||||
// check it's the right one.
|
||||
if (certCorrect)
|
||||
RsPeerId certPeerId = RsX509Cert::getCertSslId(*peercert);
|
||||
if (RsPeerId(certPeerId) != PeerId())
|
||||
{
|
||||
// then okay...
|
||||
rslog(RSL_WARNING, pqisslzone, "pqissl::Authorise_SSL_Connection() Accepting Conn. Peer: " + PeerId().toStdString());
|
||||
RsErr() << __PRETTY_FUNCTION__ << " the cert Id doesn't match the peer "
|
||||
<< "id we're trying to connect to." << std::endl;
|
||||
|
||||
//std::cerr << "pqissl::Authorise_SSL_Connection(): accepting connection from " << sockaddr_storage_iptostring(remote_addr) << std::endl;
|
||||
accept_locked(ssl_connection, sockfd, remote_addr);
|
||||
return 1;
|
||||
/* TODO: Considering how difficult is managing to get a connection to a
|
||||
* friend nowadays on the Internet because of evil NAT everywhere.
|
||||
* If the cert is from a friend anyway we should find a way to make good
|
||||
* use of this connection instead of throwing it away... */
|
||||
|
||||
reset_locked();
|
||||
return failure;
|
||||
}
|
||||
|
||||
rslog(RSL_WARNING, pqisslzone, "pqissl::Authorise_SSL_Connection() Something Wrong ... Shutdown. Peer: " + PeerId().toStdString());
|
||||
#ifdef RS_PQISSL_AUTH_REDUNDANT_CHECK
|
||||
/* At this point the actual connection authentication has already been
|
||||
* performed in AuthSSL::VerifyX509Callback, any furter authentication check
|
||||
* like the following two are redundant. */
|
||||
|
||||
// else shutdown ssl connection.
|
||||
rslog(RSL_ALERT, pqisslzone, "pqissl::Authorise_Connection_Complete() -> calling reset()");
|
||||
uint32_t authErrCode = 0;
|
||||
if(!AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode))
|
||||
{
|
||||
RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer "
|
||||
<< "certificate signature. This should never happen at this "
|
||||
<< "point!" << std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
|
||||
reset_locked();
|
||||
return 0;
|
||||
RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert);
|
||||
if( !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
||||
<< " is not friend. It is very unlikely to happen at this "
|
||||
<< "point! Either the user must have been so fast to deny "
|
||||
<< "friendship just after VerifyX509Callback have returned "
|
||||
<< "success and just before this code being executed, or "
|
||||
<< "something really fishy is happening! Share the full log "
|
||||
<< "with developers." << std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
#endif // def RS_PQISSL_AUTH_REDUNDANT_CHECK
|
||||
|
||||
Dbg2() << __PRETTY_FUNCTION__ << " Accepting connection to peer: "
|
||||
<< PeerId() << " with address: " << remote_addr << std::endl;
|
||||
|
||||
return accept_locked(ssl_connection, sockfd, remote_addr);
|
||||
}
|
||||
|
||||
|
||||
@ -1300,13 +1225,18 @@ int pqissl::accept( SSL *ssl, int fd,
|
||||
return accept_locked(ssl, fd, foreign_addr);
|
||||
}
|
||||
|
||||
int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
const sockaddr_storage &foreign_addr )
|
||||
{
|
||||
#ifdef PQISSL_DEBUG
|
||||
std::cerr << __PRETTY_FUNCTION__ << std::endl;
|
||||
#endif
|
||||
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
||||
|
||||
constexpr int failure = -1;
|
||||
constexpr int success = 1;
|
||||
|
||||
#ifdef RS_PQISSL_BANLIST_REDUNDANT_CHECK
|
||||
/* TODO: It make no sense to check banlist at this point, as we are actively
|
||||
* attempting the connection, we decide the address to which to connect to,
|
||||
* banned addresses should never get here */
|
||||
uint32_t check_result;
|
||||
uint32_t checking_flags = RSBANLIST_CHECKING_FLAGS_BLACKLIST;
|
||||
|
||||
@ -1329,14 +1259,15 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
sockaddr_storage_iptostring(foreign_addr), "", "",
|
||||
check_result);
|
||||
reset_locked();
|
||||
return -1;
|
||||
return failure;
|
||||
}
|
||||
#endif //def RS_BANLIST_REDUNDANT_CHECK
|
||||
|
||||
if (waiting != WAITING_NOT)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Peer: " << PeerId().toStdString()
|
||||
<< " - Two connections in progress - Shut 1 down!"
|
||||
<< std::endl;
|
||||
RsInfo() << __PRETTY_FUNCTION__ << " Peer: " << PeerId()
|
||||
<< " - Two connections in progress - Shut 1 down!"
|
||||
<< std::endl;
|
||||
|
||||
// outgoing connection in progress.
|
||||
// shut this baby down.
|
||||
@ -1431,7 +1362,7 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
waiting = WAITING_FAIL_INTERFACE; // failed completely.
|
||||
|
||||
reset_locked();
|
||||
return -1;
|
||||
return failure;
|
||||
}
|
||||
#ifdef PQISSL_DEBUG
|
||||
else std::cerr << __PRETTY_FUNCTION__ << " Socket made non-nlocking!"
|
||||
@ -1456,7 +1387,7 @@ int pqissl::accept_locked( SSL *ssl, int fd,
|
||||
sockaddr_storage addr; sockaddr_storage_copy(remote_addr, addr);
|
||||
parent()->notifyEvent(this, NET_CONNECT_SUCCESS, addr);
|
||||
}
|
||||
return 1;
|
||||
return success;
|
||||
}
|
||||
|
||||
/********** Implementation of BinInterface **************************
|
||||
|
@ -3,8 +3,8 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2006 by Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2015-2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2004-2006 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2015-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -20,8 +20,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef MRK_PQI_SSL_HEADER
|
||||
#define MRK_PQI_SSL_HEADER
|
||||
#pragma once
|
||||
|
||||
// operating system specific network header.
|
||||
#include "pqi/pqinetwork.h"
|
||||
@ -32,6 +31,9 @@
|
||||
#include "pqi/pqi_base.h"
|
||||
#include "pqi/authssl.h"
|
||||
|
||||
#define RS_PQISSL_AUTH_REDUNDANT_CHECK 1
|
||||
|
||||
|
||||
#define WAITING_NOT 0
|
||||
#define WAITING_DELAY 1
|
||||
#define WAITING_SOCK_CONNECT 2
|
||||
@ -159,8 +161,6 @@ int Initiate_SSL_Connection();
|
||||
int SSL_Connection_Complete();
|
||||
int Authorise_SSL_Connection();
|
||||
|
||||
int Extract_Failed_SSL_Certificate(); // try to get cert anyway.
|
||||
|
||||
// check connection timeout.
|
||||
bool CheckConnectionTimeout();
|
||||
|
||||
@ -207,9 +207,6 @@ bool CheckConnectionTimeout();
|
||||
private:
|
||||
// ssl only fns.
|
||||
int connectInterface(const struct sockaddr_storage &addr);
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // MRK_PQI_SSL_HEADER
|
||||
|
@ -20,20 +20,20 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "pqi/pqissl.h"
|
||||
#include "pqi/pqissllistener.h"
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/sslfns.h"
|
||||
|
||||
#include "pqi/p3peermgr.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "retroshare/rsbanlist.h"
|
||||
#include "pqi/authgpg.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
static struct RsLog::logInfo pqissllistenzoneInfo = {RsLog::Default, "p3peermgr"};
|
||||
#define pqissllistenzone &pqissllistenzoneInfo
|
||||
@ -486,9 +486,6 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
|
||||
break;
|
||||
}
|
||||
|
||||
/* we have failed -> get certificate if possible */
|
||||
Extract_Failed_SSL_Certificate(incoming_connexion_info);
|
||||
|
||||
closeConnection(fd, incoming_connexion_info.ssl) ;
|
||||
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, "Read Error on the SSL Socket\nShutting it down!");
|
||||
@ -502,20 +499,11 @@ int pqissllistenbase::continueSSL(IncomingSSLInfo& incoming_connexion_info, bool
|
||||
//
|
||||
X509 *x509 = SSL_get_peer_certificate(incoming_connexion_info.ssl) ;
|
||||
|
||||
#ifdef DEBUG_LISTENNER
|
||||
std::cerr << "Info from certificate: " << std::endl;
|
||||
#endif
|
||||
if(x509 != NULL)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
incoming_connexion_info.gpgid = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer)));
|
||||
incoming_connexion_info.sslcn = getX509CNString(x509->cert_info->subject);
|
||||
#else
|
||||
incoming_connexion_info.gpgid = RsPgpId(std::string(getX509CNString(X509_get_issuer_name(x509))));
|
||||
incoming_connexion_info.sslcn = getX509CNString(X509_get_subject_name(x509));
|
||||
#endif
|
||||
|
||||
getX509id(x509,incoming_connexion_info.sslid);
|
||||
if(x509)
|
||||
{
|
||||
incoming_connexion_info.gpgid = RsX509Cert::getCertIssuer(*x509);
|
||||
incoming_connexion_info.sslcn = RsX509Cert::getCertName(*x509);
|
||||
incoming_connexion_info.sslid = RsX509Cert::getCertSslId(*x509);
|
||||
|
||||
#ifdef DEBUG_LISTENNER
|
||||
std::cerr << " Got PGP Id = " << incoming_connexion_info.gpgid << std::endl;
|
||||
@ -571,61 +559,6 @@ int pqissllistenbase::closeConnection(int fd, SSL *ssl)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pqissllistenbase::Extract_Failed_SSL_Certificate(const IncomingSSLInfo& info)
|
||||
{
|
||||
pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, "pqissllistenbase::Extract_Failed_SSL_Certificate()");
|
||||
|
||||
std::cerr << "pqissllistenbase::Extract_Failed_SSL_Certificate() FAILED CONNECTION due to security!";
|
||||
std::cerr << std::endl;
|
||||
|
||||
// Get the Peer Certificate....
|
||||
X509 *peercert = SSL_get_peer_certificate(info.ssl);
|
||||
|
||||
std::cerr << "Extract_Failed_SSL_Certificate: " << std::endl;
|
||||
std::cerr << " SSL = " << (void*)info.ssl << std::endl;
|
||||
std::cerr << " GPG id = " << info.gpgid << std::endl;
|
||||
std::cerr << " SSL id = " << info.sslid << std::endl;
|
||||
std::cerr << " SSL cn = " << info.sslcn << std::endl;
|
||||
std::cerr << " addr+p = " << sockaddr_storage_tostring(info.addr) << std::endl;
|
||||
|
||||
if (peercert == NULL)
|
||||
{
|
||||
std::string out;
|
||||
out += "pqissllistenbase::Extract_Failed_SSL_Certificate() from: ";
|
||||
out += sockaddr_storage_tostring(info.addr);
|
||||
out += " ERROR Peer didn't give Cert!";
|
||||
std::cerr << out << std::endl;
|
||||
AuthSSL::getAuthSSL()->FailedCertificate(peercert, info.gpgid,info.sslid,info.sslcn,info.addr, true);
|
||||
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pqioutput(PQL_DEBUG_BASIC, pqissllistenzone,
|
||||
"pqissllistenbase::Extract_Failed_SSL_Certificate() Have Peer Cert - Registering");
|
||||
|
||||
{
|
||||
std::string out;
|
||||
out += "pqissllistenbase::Extract_Failed_SSL_Certificate() from: ";
|
||||
out += sockaddr_storage_tostring(info.addr);
|
||||
out += " Passing Cert to AuthSSL() for analysis";
|
||||
std::cerr << out << std::endl;
|
||||
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, out);
|
||||
std::cerr << out << std::endl;
|
||||
}
|
||||
|
||||
// save certificate... (and ip locations)
|
||||
// false for outgoing....
|
||||
AuthSSL::getAuthSSL()->FailedCertificate(peercert, info.gpgid,info.sslid,info.sslcn,info.addr, true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int pqissllistenbase::continueaccepts()
|
||||
{
|
||||
|
||||
@ -830,91 +763,68 @@ int pqissllistener::status()
|
||||
}
|
||||
|
||||
int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info)
|
||||
{
|
||||
{
|
||||
constexpr int failure = -1;
|
||||
constexpr int success = 1;
|
||||
|
||||
// Get the Peer Certificate....
|
||||
X509 *peercert = SSL_get_peer_certificate(info.ssl);
|
||||
|
||||
if (peercert == NULL)
|
||||
X509* peercert = SSL_get_peer_certificate(info.ssl);
|
||||
if(!peercert)
|
||||
{
|
||||
pqioutput(PQL_WARNING, pqissllistenzone,
|
||||
"pqissllistener::completeConnection() Peer Did Not Provide Cert!");
|
||||
|
||||
// failure -1, pending 0, sucess 1.
|
||||
// pqissllistenbase will shutdown!
|
||||
return -1;
|
||||
RsFatal() << __PRETTY_FUNCTION__ << " failed to retrieve peer "
|
||||
<< "certificate at this point this should never happen!"
|
||||
<< std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
|
||||
// Check cert.
|
||||
RsPeerId newPeerId;
|
||||
RsPgpId pgpId = RsX509Cert::getCertIssuer(*peercert);
|
||||
RsPeerId newPeerId = RsX509Cert::getCertSslId(*peercert);
|
||||
|
||||
#ifdef RS_PQISSL_AUTH_REDUNDANT_CHECK
|
||||
/* At this point the actual connection authentication has already been
|
||||
* performed in AuthSSL::VerifyX509Callback, any furter authentication check
|
||||
* like the following two are redundant. */
|
||||
|
||||
/****
|
||||
* As the validation is actually done before this...
|
||||
* we should only need to call CheckCertificate here!
|
||||
****/
|
||||
uint32_t authErrCode = 0;
|
||||
if(!AuthSSL::instance().AuthX509WithGPG(peercert, authErrCode))
|
||||
{
|
||||
RsFatal() << __PRETTY_FUNCTION__ << " failure verifying peer "
|
||||
<< "certificate signature. This should never happen at this "
|
||||
<< "point!" << std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
|
||||
bool certOk = AuthSSL::getAuthSSL()->ValidateCertificate(peercert, newPeerId);
|
||||
if( !AuthGPG::getAuthGPG()->isGPGAccepted(pgpId) )
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " pgpId: " << pgpId
|
||||
<< " is not friend. It is very unlikely to happen at this "
|
||||
<< "point! Either the user must have been so fast to deny "
|
||||
<< "friendship just after VerifyX509Callback have returned "
|
||||
<< "success and just before this code being executed, or "
|
||||
<< "something really fishy is happening! Share the full log "
|
||||
<< "with developers." << std::endl;
|
||||
print_stacktrace();
|
||||
exit(failure);
|
||||
}
|
||||
#endif //def RS_PQISSL_AUTH_REDUNDANT_CHECK
|
||||
|
||||
bool found = false;
|
||||
std::map<RsPeerId, pqissl *>::iterator it;
|
||||
|
||||
// Let connected one through as well! if ((npc == NULL) || (npc -> Connected()))
|
||||
if (!certOk)
|
||||
for(auto it = listenaddr.begin(); !found && it != listenaddr.end(); )
|
||||
{
|
||||
pqioutput(PQL_WARNING, pqissllistenzone,
|
||||
"pqissllistener::completeConnection() registerCertificate Failed!");
|
||||
|
||||
// bad - shutdown.
|
||||
// pqissllistenbase will shutdown!
|
||||
X509_free(peercert);
|
||||
|
||||
return -1;
|
||||
if (it -> first == newPeerId) found = true;
|
||||
else ++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string out = "pqissllistener::continueSSL()\nchecking: " + newPeerId.toStdString() + "\n";
|
||||
// check if cert is in our list.....
|
||||
for(it = listenaddr.begin();(found!=true) && (it!=listenaddr.end());)
|
||||
{
|
||||
out + "\tagainst: " + it->first.toStdString() + "\n";
|
||||
if (it -> first == newPeerId)
|
||||
{
|
||||
// accept even if already connected.
|
||||
out += "\t\tMatch!";
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
pqioutput(PQL_DEBUG_BASIC, pqissllistenzone, out);
|
||||
}
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
std::string out = "No Matching Certificate for Connection:";
|
||||
out += sockaddr_storage_tostring(info.addr);
|
||||
out += "\npqissllistenbase: Will shut it down!";
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, out);
|
||||
Dbg1() << __PRETTY_FUNCTION__ << " got secure connection from address: "
|
||||
<< info.addr << " with previously unknown SSL certificate: "
|
||||
<< newPeerId << " signed by PGP friend: " << pgpId
|
||||
<< ". Adding the new location as SSL friend." << std::endl;
|
||||
|
||||
// but as it passed the authentication step,
|
||||
// we can add it into the AuthSSL, and mConnMgr.
|
||||
|
||||
AuthSSL::getAuthSSL()->CheckCertificate(newPeerId, peercert);
|
||||
|
||||
/* now need to get GPG id too */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
RsPgpId pgpid(std::string(getX509CNString(peercert->cert_info->issuer)));
|
||||
#else
|
||||
RsPgpId pgpid(std::string(getX509CNString(X509_get_issuer_name(peercert))));
|
||||
#endif
|
||||
mPeerMgr->addFriend(newPeerId, pgpid);
|
||||
|
||||
X509_free(peercert);
|
||||
return -1;
|
||||
mPeerMgr->addFriend(newPeerId, pgpId);
|
||||
}
|
||||
|
||||
// Cleanup cert.
|
||||
@ -926,17 +836,14 @@ int pqissllistener::completeConnection(int fd, IncomingSSLInfo& info)
|
||||
as.mSSL = info.ssl;
|
||||
as.mPeerId = newPeerId;
|
||||
as.mAddr = info.addr;
|
||||
as.mAcceptTS = time(NULL);
|
||||
as.mAcceptTS = time(nullptr);
|
||||
|
||||
accepted_ssl.push_back(as);
|
||||
|
||||
std::string out = "pqissllistener::completeConnection() Successful Connection with: " + newPeerId.toStdString();
|
||||
out += " for Connection:";
|
||||
out += sockaddr_storage_tostring(info.addr);
|
||||
out += " Adding to WAIT-ACCEPT Queue";
|
||||
pqioutput(PQL_WARNING, pqissllistenzone, out);
|
||||
Dbg1() << __PRETTY_FUNCTION__ << "Successful Connection with: "
|
||||
<< newPeerId << " with address: " << info.addr << std::endl;
|
||||
|
||||
return 1;
|
||||
return success;
|
||||
}
|
||||
|
||||
int pqissllistener::finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId, const struct sockaddr_storage &remote_addr)
|
||||
|
@ -19,21 +19,20 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef MRK_PQI_SSL_LISTEN_HEADER
|
||||
#define MRK_PQI_SSL_LISTEN_HEADER
|
||||
#pragma once
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
// operating system specific network header.
|
||||
#include "pqi/pqinetwork.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "pqi/pqi_base.h"
|
||||
#include "pqi/pqilistener.h"
|
||||
|
||||
#include "pqi/authssl.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include "pqi/pqinetwork.h"
|
||||
|
||||
#define RS_PQISSL_AUTH_REDUNDANT_CHECK 1
|
||||
|
||||
/***************************** pqi Net SSL Interface *********************************
|
||||
*/
|
||||
@ -98,7 +97,7 @@ protected:
|
||||
p3PeerMgr *mPeerMgr;
|
||||
|
||||
private:
|
||||
int Extract_Failed_SSL_Certificate(const IncomingSSLInfo&);
|
||||
|
||||
bool active;
|
||||
int lsock;
|
||||
std::list<IncomingSSLInfo> incoming_ssl ;
|
||||
@ -122,7 +121,6 @@ public:
|
||||
|
||||
private:
|
||||
std::map<RsPeerId, pqissl*> listenaddr;
|
||||
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||||
};
|
||||
|
||||
|
||||
#endif // MRK_PQI_SSL_LISTEN_HEADER
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "pqi/pqi_base.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "pqi/authssl.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
@ -675,13 +676,6 @@ int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
|
||||
return(strlen(buf));
|
||||
}
|
||||
|
||||
/* XXX FIX */
|
||||
bool CheckX509Certificate(X509 */*x509*/)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t getX509SerialNumber(X509 *cert)
|
||||
{
|
||||
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
|
||||
@ -711,67 +705,39 @@ uint32_t getX509RetroshareCertificateVersion(X509 *cert)
|
||||
}
|
||||
}
|
||||
|
||||
// Not dependent on sslroot. load, and detroys the X509 memory.
|
||||
int LoadCheckX509(const char *cert_file, RsPgpId& issuerName, std::string &location, RsPeerId &userId)
|
||||
int LoadCheckX509(
|
||||
const char* cert_file, RsPgpId& issuer, std::string& location,
|
||||
RsPeerId& userId )
|
||||
{
|
||||
/* This function loads the X509 certificate from the file,
|
||||
* and checks the certificate
|
||||
*/
|
||||
constexpr int failure = 0;
|
||||
constexpr int success = 1;
|
||||
|
||||
FILE *tmpfp = RsDirUtil::rs_fopen(cert_file, "r");
|
||||
if (tmpfp == NULL)
|
||||
if (tmpfp == nullptr)
|
||||
{
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "sslroot::LoadCheckAndGetX509Name()";
|
||||
std::cerr << " Failed to open Certificate File:" << cert_file;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return 0;
|
||||
RsErr() << __PRETTY_FUNCTION__ << " Failed to open Certificate File: "
|
||||
<< cert_file << std::endl;
|
||||
return failure;
|
||||
}
|
||||
|
||||
// get xPGP certificate.
|
||||
X509 *x509 = PEM_read_X509(tmpfp, NULL, NULL, NULL);
|
||||
X509* x509 = PEM_read_X509(tmpfp, nullptr, nullptr, nullptr);
|
||||
fclose(tmpfp);
|
||||
|
||||
// check the certificate.
|
||||
bool valid = false;
|
||||
if (x509)
|
||||
if(!x509)
|
||||
{
|
||||
valid = CheckX509Certificate(x509);
|
||||
if (valid)
|
||||
{
|
||||
valid = getX509id(x509, userId);
|
||||
}
|
||||
RsErr() << __PRETTY_FUNCTION__ << " PEM_read_X509 failed!" << std::endl;
|
||||
return failure;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
// extract the name.
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
issuerName = RsPgpId(std::string(getX509CNString(x509->cert_info->issuer)));
|
||||
location = getX509LocString(x509->cert_info->subject);
|
||||
#else
|
||||
issuerName = RsPgpId(std::string(getX509CNString(X509_get_issuer_name(x509))));
|
||||
location = getX509LocString(X509_get_subject_name(x509));
|
||||
#endif
|
||||
}
|
||||
userId = RsX509Cert::getCertSslId(*x509);
|
||||
issuer = RsX509Cert::getCertIssuer(*x509);
|
||||
location = RsX509Cert::getCertLocation(*x509);
|
||||
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cout << getX509Info(x509) << std::endl ;
|
||||
#endif
|
||||
// clean up.
|
||||
X509_free(x509);
|
||||
|
||||
if (valid)
|
||||
{
|
||||
// happy!
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// something went wrong!
|
||||
return 0;
|
||||
}
|
||||
if(userId.isNull() || issuer.isNull()) return failure;
|
||||
else return success;
|
||||
}
|
||||
|
||||
std::string getX509NameString(X509_NAME *name)
|
||||
@ -896,10 +862,9 @@ std::string getX509Info(X509 *cert)
|
||||
|
||||
/********** SSL ERROR STUFF ******************************************/
|
||||
|
||||
int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::string &out)
|
||||
int printSSLError(
|
||||
SSL*, int retval, int err, unsigned long err2, std::string& out )
|
||||
{
|
||||
(void) ssl; /* remove unused parameter warnings */
|
||||
|
||||
std::string reason;
|
||||
|
||||
std::string mainreason = std::string("UNKNOWN ERROR CODE");
|
||||
@ -939,7 +904,18 @@ int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::string
|
||||
{
|
||||
mainreason = std::string("SSL_ERROR_SSL");
|
||||
}
|
||||
rs_sprintf_append(out, "RetVal(%d) -> SSL Error: %s\n\t + ERR Error: %s\n", retval, mainreason.c_str(), ERR_error_string(err2, NULL));
|
||||
rs_sprintf_append( out,
|
||||
"RetVal(%d) -> SSL Error: %s\n\t + ERR Error: %s\n",
|
||||
retval, mainreason.c_str(),
|
||||
ERR_error_string(err2, nullptr) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
std::string sslErrorToString(int retval, int err, unsigned long err2)
|
||||
{
|
||||
std::string ret;
|
||||
// When printSSLError will be removed it's code will be moved here
|
||||
printSSLError(nullptr, retval, err, err2, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*******************************************************************************
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/pqi: sslfns.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
@ -19,8 +19,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef RS_PQI_SSL_HELPER_H
|
||||
#define RS_PQI_SSL_HELPER_H
|
||||
#pragma once
|
||||
|
||||
/* Functions in this file are SSL only,
|
||||
* and have no dependence on SSLRoot() etc.
|
||||
@ -32,9 +31,12 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <retroshare/rstypes.h>
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "util/rsdeprecate.h"
|
||||
#include "retroshare/rstypes.h"
|
||||
|
||||
|
||||
/****
|
||||
* #define AUTHSSL_DEBUG 1
|
||||
@ -113,9 +115,12 @@ bool getX509id(X509 *x509, RsPeerId &xid);
|
||||
|
||||
int pem_passwd_cb(char *buf, int size, int rwflag, void *password);
|
||||
|
||||
bool CheckX509Certificate(X509 *x509);
|
||||
// Not dependent on sslroot. load, and detroys the X509 memory.
|
||||
int LoadCheckX509(const char *cert_file, RsPgpId& issuer, std::string &location, RsPeerId& userId);
|
||||
/** This function loads the X509 certificate from the file, and checks the
|
||||
* certificate.
|
||||
* Not dependent on sslroot. load, and detroys the X509 memory. */
|
||||
int LoadCheckX509(
|
||||
const char* cert_file, RsPgpId& issuer, std::string& location,
|
||||
RsPeerId& userId );
|
||||
|
||||
|
||||
std::string getX509NameString(X509_NAME *name);
|
||||
@ -131,7 +136,8 @@ uint32_t getX509RetroshareCertificateVersion(X509 *cert) ;
|
||||
|
||||
/********** SSL ERROR STUFF ******************************************/
|
||||
|
||||
int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::string &out);
|
||||
|
||||
#endif /* RS_PQI_SSL_HELPER_H */
|
||||
RS_DEPRECATED_FOR(sslErrorToString)
|
||||
int printSSLError(
|
||||
SSL* unused, int retval, int err, unsigned long err2, std::string& out);
|
||||
|
||||
std::string sslErrorToString(int retval, int err, unsigned long err2);
|
||||
|
@ -397,9 +397,8 @@ int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
|
||||
* 2) Get List of Available Accounts.
|
||||
* 4) Get List of GPG Accounts.
|
||||
*/
|
||||
/* create singletons */
|
||||
AuthSSL::AuthSSLInit();
|
||||
AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL, "");
|
||||
/* Initialize AuthSSL */
|
||||
AuthSSL::instance().InitAuth(nullptr, nullptr, nullptr, "");
|
||||
|
||||
rsLoginHelper = new RsLoginHelper;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user