mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-21 21:55:15 -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 "authgpg.h"
|
||||
#include "pqi/p3connmgr.h"
|
||||
|
||||
/******************** notify of new Cert **************************/
|
||||
#include "pqinotify.h"
|
||||
@ -52,6 +53,10 @@
|
||||
// initialisation du pointeur de singleton à zéro
|
||||
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)
|
||||
{
|
||||
certificate = x509;
|
||||
@ -587,6 +592,36 @@ SSL_CTX *AuthSSL::getCTX()
|
||||
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)
|
||||
{
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
@ -1880,13 +1915,37 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days)
|
||||
|
||||
bool AuthSSL::AuthX509(X509 *x509)
|
||||
{
|
||||
fprintf(stderr, "AuthSSL::AuthX509() called\n");
|
||||
|
||||
RsStackMutex stack(sslMtx); /******* LOCKED ******/
|
||||
|
||||
/* extract CN for peer Id */
|
||||
X509_NAME *issuer = X509_get_issuer_name(x509);
|
||||
std::string id = "";
|
||||
std::string issuer = getX509CNString(x509->cert_info->issuer);
|
||||
//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) ***/
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fprintf(stderr, "Failing Normal Certificate!!!\n");
|
||||
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) {
|
||||
fprintf(stderr, "AuthSSL::VerifyX509Callback returned true.\n");
|
||||
} else {
|
||||
|
@ -57,6 +57,8 @@ typedef std::string SSL_id;
|
||||
|
||||
class AuthSSL;
|
||||
|
||||
class p3ConnectMgr;
|
||||
|
||||
class sslcert
|
||||
{
|
||||
public:
|
||||
@ -96,6 +98,7 @@ virtual int InitAuth(const char *srvr_cert, const char *priv_key,
|
||||
const char *passwd);
|
||||
virtual bool CloseAuth();
|
||||
virtual int setConfigDirectories(std::string confFile, std::string neighDir);
|
||||
SSL_CTX * getNewSslCtx();
|
||||
|
||||
|
||||
/*********** 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 */
|
||||
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 */
|
||||
@ -170,7 +174,9 @@ bool loadCertificates(bool &oldFormat, std::map<std::string, std::string> &key
|
||||
static AuthSSL *getAuthSSL() throw() // pour obtenir l'instance
|
||||
{ return instance_ssl; }
|
||||
|
||||
private:
|
||||
p3ConnectMgr *mConnMgr;
|
||||
|
||||
private:
|
||||
|
||||
// the single instance of this
|
||||
static AuthSSL *instance_ssl;
|
||||
|
@ -945,7 +945,9 @@ int pqissl::Initiate_SSL_Connection()
|
||||
|
||||
// Perform SSL magic.
|
||||
// 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)
|
||||
{
|
||||
rslog(RSL_ALERT, pqisslzone,
|
||||
@ -960,7 +962,11 @@ int pqissl::Initiate_SSL_Connection()
|
||||
|
||||
ssl_connection = ssl;
|
||||
|
||||
net_internal_SSL_set_fd(ssl, sockfd);
|
||||
//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);
|
||||
if (err < 1)
|
||||
{
|
||||
std::ostringstream out;
|
||||
@ -1065,16 +1071,9 @@ int pqissl::Extract_Failed_SSL_Certificate()
|
||||
"pqissl::Extract_Failed_SSL_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);
|
||||
#endif /* X509 Certificates */
|
||||
/**************** PQI_USE_XPGP ******************/
|
||||
|
||||
if (peercert == NULL)
|
||||
if (peercert == NULL)
|
||||
{
|
||||
rslog(RSL_WARNING, pqisslzone,
|
||||
"pqissl::Extract_Failed_SSL_Certificate() Peer Didnt Give Cert");
|
||||
@ -1158,7 +1157,7 @@ int pqissl::Authorise_SSL_Connection()
|
||||
|
||||
accept(ssl_connection, sockfd, remote_addr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
@ -1886,6 +1886,7 @@ int RsServer::StartupRetroShare()
|
||||
rsNotify = new p3Notify();
|
||||
|
||||
mConnMgr = new p3ConnectMgr();
|
||||
AuthSSL::getAuthSSL()->mConnMgr = mConnMgr;
|
||||
//load all the SSL certs as friends
|
||||
std::list<std::string> sslIds;
|
||||
AuthSSL::getAuthSSL()->getAuthenticatedList(sslIds);
|
||||
|
Loading…
Reference in New Issue
Block a user