mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-22 06:05:08 -05:00
allow ssl connection with a new cert, ad a friend when happening
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@2014 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
bb45fa3db5
commit
485f27dc11
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "pqinetwork.h"
|
#include "pqinetwork.h"
|
||||||
#include "authgpg.h"
|
#include "authgpg.h"
|
||||||
|
#include "pqi/p3connmgr.h"
|
||||||
|
|
||||||
/******************** notify of new Cert **************************/
|
/******************** notify of new Cert **************************/
|
||||||
#include "pqinotify.h"
|
#include "pqinotify.h"
|
||||||
@ -52,6 +53,10 @@
|
|||||||
// initialisation du pointeur de singleton à zéro
|
// initialisation du pointeur de singleton à zéro
|
||||||
AuthSSL *AuthSSL::instance_ssl = new AuthSSL();
|
AuthSSL *AuthSSL::instance_ssl = new AuthSSL();
|
||||||
|
|
||||||
|
// initialisation du pointeur de ex data du ssl context
|
||||||
|
int AuthSSL::ex_data_ctx_index = 0;
|
||||||
|
|
||||||
|
|
||||||
sslcert::sslcert(X509 *x509, std::string pid)
|
sslcert::sslcert(X509 *x509, std::string pid)
|
||||||
{
|
{
|
||||||
certificate = x509;
|
certificate = x509;
|
||||||
@ -587,6 +592,36 @@ SSL_CTX *AuthSSL::getCTX()
|
|||||||
return sslctx;
|
return sslctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Context handling */
|
||||||
|
SSL_CTX *AuthSSL::getNewSslCtx()
|
||||||
|
{
|
||||||
|
#ifdef AUTHSSL_DEBUG
|
||||||
|
std::cerr << "AuthSSL::getNewSslCtx()";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
// setup connection method
|
||||||
|
SSL_CTX *newSslctx = SSL_CTX_new(TLSv1_method());
|
||||||
|
|
||||||
|
// setup cipher lists.
|
||||||
|
SSL_CTX_set_cipher_list(newSslctx, "DEFAULT");
|
||||||
|
|
||||||
|
// certificates (Set Local Server Certificate).
|
||||||
|
SSL_CTX_use_certificate(newSslctx, mOwnCert->certificate);
|
||||||
|
|
||||||
|
// get private key
|
||||||
|
SSL_CTX_use_PrivateKey(newSslctx, pkey);
|
||||||
|
|
||||||
|
// enable verification of certificates (PEER)
|
||||||
|
// and install verify callback.
|
||||||
|
SSL_CTX_set_verify(newSslctx, SSL_VERIFY_PEER |
|
||||||
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||||
|
verify_x509_callback);
|
||||||
|
|
||||||
|
std::cerr << "getNewSslCtx() finished" << std::endl;
|
||||||
|
|
||||||
|
return newSslctx;
|
||||||
|
}
|
||||||
|
|
||||||
int AuthSSL::setConfigDirectories(std::string configfile, std::string neighdir)
|
int AuthSSL::setConfigDirectories(std::string configfile, std::string neighdir)
|
||||||
{
|
{
|
||||||
#ifdef AUTHSSL_DEBUG
|
#ifdef AUTHSSL_DEBUG
|
||||||
@ -1880,13 +1915,37 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days)
|
|||||||
|
|
||||||
bool AuthSSL::AuthX509(X509 *x509)
|
bool AuthSSL::AuthX509(X509 *x509)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "AuthSSL::AuthX509() called\n");
|
||||||
|
|
||||||
RsStackMutex stack(sslMtx); /******* LOCKED ******/
|
RsStackMutex stack(sslMtx); /******* LOCKED ******/
|
||||||
|
|
||||||
/* extract CN for peer Id */
|
/* extract CN for peer Id */
|
||||||
X509_NAME *issuer = X509_get_issuer_name(x509);
|
std::string issuer = getX509CNString(x509->cert_info->issuer);
|
||||||
std::string id = "";
|
//check that the issuer is in the accepted GPG key list.
|
||||||
|
std::list<std::string> acceptedIds;
|
||||||
|
AuthGPG::getAuthGPG()->getPGPAcceptedList(acceptedIds);
|
||||||
|
bool isAccepted = false;
|
||||||
|
for(std::list<std::string>::iterator it = acceptedIds.begin(); it != acceptedIds.end(); it++){
|
||||||
|
std::cerr << "AuthSSL::AuthX509() : accepted id : " << *it << std::endl;
|
||||||
|
if (*it == issuer) {
|
||||||
|
isAccepted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isAccepted) {
|
||||||
|
//check that the gpg key is not one of our private key usefull for initialisation
|
||||||
|
AuthGPG::getAuthGPG()->availablePGPCertificatesWithPrivateKeys(acceptedIds);
|
||||||
|
bool isAccepted = false;
|
||||||
|
for(std::list<std::string>::iterator it = acceptedIds.begin(); it != acceptedIds.end(); it++){
|
||||||
|
std::cerr << "AuthSSL::AuthX509() : accepted id : " << *it << std::endl;
|
||||||
|
if (*it == issuer) {
|
||||||
|
isAccepted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* verify signature */
|
/* verify GPG signature */
|
||||||
|
|
||||||
/*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/
|
/*** NOW The Manual signing bit (HACKED FROM asn1/a_sign.c) ***/
|
||||||
int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF;
|
int (*i2d)(X509_CINF*, unsigned char**) = i2d_X509_CINF;
|
||||||
@ -2132,12 +2191,68 @@ int AuthSSL::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|||||||
}
|
}
|
||||||
preverify_ok = true;
|
preverify_ok = true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Failing Normal Certificate!!!\n");
|
fprintf(stderr, "Failing Normal Certificate!!!\n");
|
||||||
preverify_ok = false;
|
preverify_ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preverify_ok) {
|
||||||
|
//add the cert to our collection if not already in it
|
||||||
|
bool found = false;
|
||||||
|
std::string certId;
|
||||||
|
{
|
||||||
|
RsStackMutex stack(sslMtx);
|
||||||
|
sslcert *cert = NULL;
|
||||||
|
getX509id(X509_STORE_CTX_get_current_cert(ctx), certId);
|
||||||
|
found = locked_FindCert(certId, &cert);
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
std::cerr << "AuthSSL::VerifyX509Callback adding new SSL friend" << std::endl;
|
||||||
|
//first we want to ceate a new x509 because when SSL connection will be destroyed we will loose ref to the current x509
|
||||||
|
std::string copyCertstr;
|
||||||
|
BIO *bp = BIO_new(BIO_s_mem());
|
||||||
|
PEM_write_bio_X509(bp, X509_STORE_CTX_get_current_cert(ctx));
|
||||||
|
char *data;
|
||||||
|
int len = BIO_get_mem_data(bp, &data);
|
||||||
|
for(int i = 0; i < len; i++) {
|
||||||
|
copyCertstr += data[i];
|
||||||
|
}
|
||||||
|
BIO_free(bp);
|
||||||
|
|
||||||
|
//create a new x509 from the copyCertstr
|
||||||
|
char *certstr = strdup(copyCertstr.c_str());
|
||||||
|
BIO *bp2 = BIO_new_mem_buf(certstr, -1);
|
||||||
|
X509 *certCopy = PEM_read_bio_X509(bp2, NULL, NULL, NULL);
|
||||||
|
BIO_free(bp2);
|
||||||
|
free(certstr);
|
||||||
|
|
||||||
|
if (certCopy) {
|
||||||
|
AuthSSL::getAuthSSL()->ProcessX509(certCopy, certId);
|
||||||
|
mConnMgr->addFriend(certId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check that the peerid in the context is the same as the cert one
|
||||||
|
SSL *ssl = (SSL*) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||||
|
if (SSL_get_ex_data(ssl, AuthSSL::ex_data_ctx_index)) {
|
||||||
|
char *peer_id_in_context = (char*) SSL_get_ex_data(ssl, AuthSSL::ex_data_ctx_index);
|
||||||
|
if (std::string(certId.c_str()) != std::string(peer_id_in_context)) {
|
||||||
|
//the connection was asked for a given peer and get connected top another peer
|
||||||
|
fprintf(stderr, "AuthSSL::VerifyX509Callback peer id in context not the same as cert, aborting connection.");
|
||||||
|
preverify_ok = false;
|
||||||
|
|
||||||
|
//tranfer the ip address to the new peer
|
||||||
|
peerConnectState detail;
|
||||||
|
if (mConnMgr->getFriendNetStatus(peer_id_in_context, detail)) {
|
||||||
|
mConnMgr->setAddressList(certId, detail.getIpAddressList());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "AuthSSL::VerifyX509Callback peer id in context is the same as cert, continung connection.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (preverify_ok) {
|
if (preverify_ok) {
|
||||||
fprintf(stderr, "AuthSSL::VerifyX509Callback returned true.\n");
|
fprintf(stderr, "AuthSSL::VerifyX509Callback returned true.\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,6 +57,8 @@ typedef std::string SSL_id;
|
|||||||
|
|
||||||
class AuthSSL;
|
class AuthSSL;
|
||||||
|
|
||||||
|
class p3ConnectMgr;
|
||||||
|
|
||||||
class sslcert
|
class sslcert
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -96,6 +98,7 @@ virtual int InitAuth(const char *srvr_cert, const char *priv_key,
|
|||||||
const char *passwd);
|
const char *passwd);
|
||||||
virtual bool CloseAuth();
|
virtual bool CloseAuth();
|
||||||
virtual int setConfigDirectories(std::string confFile, std::string neighDir);
|
virtual int setConfigDirectories(std::string confFile, std::string neighDir);
|
||||||
|
SSL_CTX * getNewSslCtx();
|
||||||
|
|
||||||
|
|
||||||
/*********** Overloaded Functions from p3AuthMgr **********/
|
/*********** Overloaded Functions from p3AuthMgr **********/
|
||||||
@ -159,6 +162,7 @@ virtual bool ValidateCertificate(X509 *x509, std::string &peerId); /* validate
|
|||||||
|
|
||||||
public: /* SSL specific functions used in pqissl/pqissllistener */
|
public: /* SSL specific functions used in pqissl/pqissllistener */
|
||||||
SSL_CTX *getCTX();
|
SSL_CTX *getCTX();
|
||||||
|
static int ex_data_ctx_index; //used to pass the peer id in the ssl context
|
||||||
|
|
||||||
|
|
||||||
bool FailedCertificate(X509 *x509, bool incoming); /* store for discovery */
|
bool FailedCertificate(X509 *x509, bool incoming); /* store for discovery */
|
||||||
@ -170,6 +174,8 @@ bool loadCertificates(bool &oldFormat, std::map<std::string, std::string> &key
|
|||||||
static AuthSSL *getAuthSSL() throw() // pour obtenir l'instance
|
static AuthSSL *getAuthSSL() throw() // pour obtenir l'instance
|
||||||
{ return instance_ssl; }
|
{ return instance_ssl; }
|
||||||
|
|
||||||
|
p3ConnectMgr *mConnMgr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// the single instance of this
|
// the single instance of this
|
||||||
|
@ -945,7 +945,9 @@ int pqissl::Initiate_SSL_Connection()
|
|||||||
|
|
||||||
// Perform SSL magic.
|
// Perform SSL magic.
|
||||||
// library already inited by sslroot().
|
// library already inited by sslroot().
|
||||||
SSL *ssl = SSL_new(AuthSSL::getAuthSSL()->getCTX());
|
SSL_CTX *ssl_ctx = AuthSSL::getAuthSSL()->getCTX();
|
||||||
|
|
||||||
|
SSL *ssl = SSL_new(ssl_ctx);
|
||||||
if (ssl == NULL)
|
if (ssl == NULL)
|
||||||
{
|
{
|
||||||
rslog(RSL_ALERT, pqisslzone,
|
rslog(RSL_ALERT, pqisslzone,
|
||||||
@ -960,6 +962,10 @@ int pqissl::Initiate_SSL_Connection()
|
|||||||
|
|
||||||
ssl_connection = ssl;
|
ssl_connection = ssl;
|
||||||
|
|
||||||
|
//store the peer id in the context for the callback check
|
||||||
|
AuthSSL::ex_data_ctx_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
||||||
|
SSL_set_ex_data(ssl, AuthSSL::ex_data_ctx_index, const_cast<char*> (PeerId().c_str()));
|
||||||
|
|
||||||
net_internal_SSL_set_fd(ssl, sockfd);
|
net_internal_SSL_set_fd(ssl, sockfd);
|
||||||
if (err < 1)
|
if (err < 1)
|
||||||
{
|
{
|
||||||
@ -1065,14 +1071,7 @@ int pqissl::Extract_Failed_SSL_Certificate()
|
|||||||
"pqissl::Extract_Failed_SSL_Certificate()");
|
"pqissl::Extract_Failed_SSL_Certificate()");
|
||||||
|
|
||||||
// Get the Peer Certificate....
|
// Get the Peer Certificate....
|
||||||
/**************** PQI_USE_XPGP ******************/
|
|
||||||
#if defined(PQI_USE_XPGP)
|
|
||||||
XPGP *peercert = SSL_get_peer_pgp_certificate(ssl_connection);
|
|
||||||
#else /* X509 Certificates */
|
|
||||||
/**************** PQI_USE_XPGP ******************/
|
|
||||||
X509 *peercert = SSL_get_peer_certificate(ssl_connection);
|
X509 *peercert = SSL_get_peer_certificate(ssl_connection);
|
||||||
#endif /* X509 Certificates */
|
|
||||||
/**************** PQI_USE_XPGP ******************/
|
|
||||||
|
|
||||||
if (peercert == NULL)
|
if (peercert == NULL)
|
||||||
{
|
{
|
||||||
|
@ -1886,6 +1886,7 @@ int RsServer::StartupRetroShare()
|
|||||||
rsNotify = new p3Notify();
|
rsNotify = new p3Notify();
|
||||||
|
|
||||||
mConnMgr = new p3ConnectMgr();
|
mConnMgr = new p3ConnectMgr();
|
||||||
|
AuthSSL::getAuthSSL()->mConnMgr = mConnMgr;
|
||||||
//load all the SSL certs as friends
|
//load all the SSL certs as friends
|
||||||
std::list<std::string> sslIds;
|
std::list<std::string> sslIds;
|
||||||
AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
|
AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
|
||||||
|
Loading…
Reference in New Issue
Block a user