diff --git a/libretroshare/src/dht/dhtclient.h b/libretroshare/src/dht/dhtclient.h index 578a7f946..e6968b138 100644 --- a/libretroshare/src/dht/dhtclient.h +++ b/libretroshare/src/dht/dhtclient.h @@ -55,17 +55,17 @@ class DHTClientDummy: public DHTClient public: /* initialise from file */ -virtual bool checkServerFile(std::string filename) { return false; } -virtual bool loadServers(std::string filename) { return true; } -virtual bool loadServersFromWeb(std::string storename) { return true; } +virtual bool checkServerFile(std::string) { return true; } +virtual bool loadServers(std::string) { return true; } +virtual bool loadServersFromWeb(std::string) { return true; } virtual bool loadServers(std::istream&) { return true; } /* check that its working */ virtual bool dhtActive() { return true; } /* publish / search */ -virtual bool publishKey(std::string key, std::string value, uint32_t ttl) { return true; } -virtual bool searchKey(std::string key, std::list &values) { return true; } +virtual bool publishKey(std::string, std::string, uint32_t) { return true; } +virtual bool searchKey(std::string, std::list &) { return true; } }; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index b74a48238..efd283320 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -210,6 +210,7 @@ HEADERS += dbase/cachestrapper.h \ ft/ftserver.h \ ft/fttransfermodule.h \ # ft/ftdwlqueue.h \ + pqi/sslfns.h \ pqi/authssl.h \ pqi/authgpg.h \ pqi/cleanupxpgp.h \ @@ -330,6 +331,32 @@ HEADERS += dbase/cachestrapper.h \ # dht/dht_bootstrap.cc \ SOURCES += \ + pqi/sslfns.cc \ + pqi/authssl.cc \ + pqi/authgpg.cc \ + pqi/cleanupxpgp.cc \ + pqi/p3notify.cc \ + pqi/pqipersongrp.cc \ + pqi/pqihandler.cc \ + pqi/pqiservice.cc \ + pqi/pqiperson.cc \ + pqi/pqissludp.cc \ + pqi/pqisslpersongrp.cc \ + pqi/pqissllistener.cc \ + pqi/pqissl.cc \ + pqi/pqissltunnel.cc \ + pqi/pqistore.cc \ +# pqi/p3authmgr.cc \ + pqi/p3cfgmgr.cc \ + pqi/p3connmgr.cc \ + pqi/p3dhtmgr.cc \ + pqi/pqiarchive.cc \ + pqi/pqibin.cc \ + pqi/pqimonitor.cc \ + pqi/pqistreamer.cc \ + pqi/pqiloopback.cc \ + pqi/pqinetwork.cc \ + pqi/pqisecurity.cc \ rsserver/p3face-msgs.cc \ rsserver/rsiface.cc \ rsserver/rstypes.cc \ @@ -379,31 +406,6 @@ SOURCES += \ dbase/fistore.cc \ dbase/fimonitor.cc \ dbase/findex.cc \ - pqi/authssl.cc \ - pqi/authgpg.cc \ - pqi/cleanupxpgp.cc \ - pqi/p3notify.cc \ - pqi/pqipersongrp.cc \ - pqi/pqihandler.cc \ - pqi/pqiservice.cc \ - pqi/pqiperson.cc \ - pqi/pqissludp.cc \ - pqi/pqisslpersongrp.cc \ - pqi/pqissllistener.cc \ - pqi/pqissl.cc \ - pqi/pqissltunnel.cc \ - pqi/pqistore.cc \ -# pqi/p3authmgr.cc \ - pqi/p3cfgmgr.cc \ - pqi/p3connmgr.cc \ - pqi/p3dhtmgr.cc \ - pqi/pqiarchive.cc \ - pqi/pqibin.cc \ - pqi/pqimonitor.cc \ - pqi/pqistreamer.cc \ - pqi/pqiloopback.cc \ - pqi/pqinetwork.cc \ - pqi/pqisecurity.cc \ serialiser/rsblogitems.cc \ serialiser/rsstatusitems.cc \ serialiser/rschannelitems.cc \ diff --git a/libretroshare/src/pqi/authssl.cc b/libretroshare/src/pqi/authssl.cc index 2dc592a55..253633535 100644 --- a/libretroshare/src/pqi/authssl.cc +++ b/libretroshare/src/pqi/authssl.cc @@ -29,6 +29,7 @@ */ #include "authssl.h" +#include "sslfns.h" #include "cleanupxpgp.h" #include "pqinetwork.h" @@ -39,9 +40,10 @@ #include "pqinotify.h" #include -#include -#include +//#include +//#include #include +#include #include #include @@ -52,7 +54,11 @@ /********************************************************************************/ /********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ /********************************************************************************/ +/********************************************************************************/ + +static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx); // initialisation du pointeur de singleton à zéro @@ -73,339 +79,29 @@ sslcert::sslcert(X509 *x509, std::string pid) authed = false; } -sslcert::sslcert() -{ - email = ""; - authed = false; -} - -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString) -{ - /* generate request */ - X509_REQ *req=X509_REQ_new(); - - // setup output. - BIO *bio_out = NULL; - bio_out = BIO_new(BIO_s_file()); - BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); - - EVP_PKEY *pkey = NULL; - - // first generate a key.... - if ((pkey=EVP_PKEY_new()) == NULL) - { - fprintf(stderr,"GenerateX509Req: Couldn't Create Key\n"); - return 0; - } - - int nbits = 2048; - unsigned long e = 0x10001; - - if ((nbits_in >= 512) && (nbits_in <= 4096)) - { - nbits = nbits_in; - } - else - { - fprintf(stderr,"GenerateX509Req: strange num of nbits: %d\n", nbits_in); - fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits); - } - - - RSA *rsa = RSA_generate_key(nbits, e, NULL, NULL); - if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) - { - if(rsa) RSA_free(rsa); - fprintf(stderr,"GenerateX509Req: Couldn't Generate RSA Key!\n"); - return 0; - } - - - // open the file. - FILE *out; - if (NULL == (out = fopen(pkey_file.c_str(), "w"))) - { - fprintf(stderr,"GenerateX509Req: Couldn't Create Key File!"); - fprintf(stderr," : %s\n", pkey_file.c_str()); - return 0; - } - - const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); - - if (!PEM_write_PrivateKey(out,pkey,cipher, - NULL,0,NULL,(void *) passwd.c_str())) - { - fprintf(stderr,"GenerateX509Req() Couldn't Save Private Key"); - fprintf(stderr," : %s\n", pkey_file.c_str()); - return 0; - } - fclose(out); - - // We have now created a private key.... - fprintf(stderr,"GenerateX509Req() Saved Private Key"); - fprintf(stderr," : %s\n", pkey_file.c_str()); - - /********** Test Loading the private Key.... ************/ - FILE *tst_in = NULL; - EVP_PKEY *tst_pkey = NULL; - if (NULL == (tst_in = fopen(pkey_file.c_str(), "rb"))) - { - fprintf(stderr,"GenerateX509Req() Couldn't Open Private Key"); - fprintf(stderr," : %s\n", pkey_file.c_str()); - return 0; - } - - if (NULL == (tst_pkey = - PEM_read_PrivateKey(tst_in,NULL,NULL,(void *) passwd.c_str()))) - { - fprintf(stderr,"GenerateX509Req() Couldn't Read Private Key"); - fprintf(stderr," : %s\n", pkey_file.c_str()); - return 0; - } - fclose(tst_in); - EVP_PKEY_free(tst_pkey); - /********** Test Loading the private Key.... ************/ - - /* Fill in details: fields. - req->req_info; - req->req_info->enc; - req->req_info->version; - req->req_info->subject; - req->req_info->pubkey; - ****************************/ - - long version = 0x00; - unsigned long chtype = MBSTRING_ASC; - X509_NAME *x509_name = X509_NAME_new(); - - // fill in the request. - - /**** X509_REQ -> Version ********************************/ - if (!X509_REQ_set_version(req,version)) /* version 1 */ - { - fprintf(stderr,"GenerateX509Req(): Couldn't Set Version!\n"); - return 0; - } - /**** X509_REQ -> Version ********************************/ - /**** X509_REQ -> Key ********************************/ - - if (!X509_REQ_set_pubkey(req,pkey)) - { - fprintf(stderr,"GenerateX509Req() Couldn't Set PUBKEY !\n"); - return 0; - } - - /**** SUBJECT ********************************/ - // create the name. - - // fields to add. - // commonName CN - // emailAddress (none) - // organizationName O - // localityName L - // stateOrProvinceName ST - // countryName C - - if (0 < strlen(name.c_str())) - { - X509_NAME_add_entry_by_txt(x509_name, "CN", chtype, - (unsigned char *) name.c_str(), -1, -1, 0); - } - else - { - fprintf(stderr,"GenerateX509Req(): No Name -> Not creating X509 Cert Req\n"); - return 0; - } - - if (0 < strlen(email.c_str())) - { - //X509_NAME_add_entry_by_txt(x509_name, "Email", 0, - // (unsigned char *) ui -> gen_email -> value(), -1, -1, 0); - X509_NAME_add_entry_by_NID(x509_name, 48, 0, - (unsigned char *) email.c_str(), -1, -1, 0); - } - - if (0 < strlen(org.c_str())) - { - X509_NAME_add_entry_by_txt(x509_name, "O", chtype, - (unsigned char *) org.c_str(), -1, -1, 0); - } - - if (0 < strlen(loc.c_str())) - { - X509_NAME_add_entry_by_txt(x509_name, "L", chtype, - (unsigned char *) loc.c_str(), -1, -1, 0); - } - - if (0 < strlen(state.c_str())) - { - X509_NAME_add_entry_by_txt(x509_name, "ST", chtype, - (unsigned char *) state.c_str(), -1, -1, 0); - } - - if (0 < strlen(country.c_str())) - { - X509_NAME_add_entry_by_txt(x509_name, "C", chtype, - (unsigned char *) country.c_str(), -1, -1, 0); - } - - if (!X509_REQ_set_subject_name(req,x509_name)) - { - fprintf(stderr,"GenerateX509Req() Couldn't Set Name to Request!\n"); - X509_NAME_free(x509_name); - return 0; - } - - X509_NAME_free(x509_name); - /**** SUBJECT ********************************/ - - if (!X509_REQ_sign(req,pkey,EVP_sha1())) - { - fprintf(stderr,"GenerateX509Req() Failed to Sign REQ\n"); - return 0; - } - - return req; -} - -#define SERIAL_RAND_BITS 64 - -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days) -{ - const EVP_MD *digest = EVP_sha1(); - ASN1_INTEGER *serial = ASN1_INTEGER_new(); - EVP_PKEY *tmppkey; - X509 *x509 = X509_new(); - if (x509 == NULL) - return NULL; - - BIGNUM *btmp = BN_new(); - if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pseudo_rand\n"); - - return NULL; - } - if (!BN_to_ASN1_INTEGER(btmp, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," int\n"); - - return NULL; - } - BN_free(btmp); - - if (!X509_set_serialNumber(x509, serial)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," serialNumber\n"); - - return NULL; - } - ASN1_INTEGER_free(serial); - - if (!X509_set_issuer_name(x509, issuer)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," issuer\n"); - - return NULL; - } - - if (!X509_gmtime_adj(x509->cert_info->validity->notBefore, 0)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notBefore\n"); - - return NULL; - } - - //x509->cert_info->validity->notAfter - //if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) - if (!X509_gmtime_adj(x509->cert_info->validity->notAfter, (long)60*60*24*days)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," notAfter\n"); - - return NULL; - } - - if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," subject_name\n"); - - return NULL; - } - - - tmppkey = X509_REQ_get_pubkey(req); - if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) - { - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," pubkey\n"); - - return NULL; - } - - - /* Cleanup Algorithm part */ - - X509_ALGOR *algor1 = x509->cert_info->signature; - X509_ALGOR *algor2 = x509->sig_alg; - - X509_ALGOR *a; - - a = algor1; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - a = algor2; - ASN1_TYPE_free(a->parameter); - a->parameter=ASN1_TYPE_new(); - a->parameter->type=V_ASN1_NULL; - - ASN1_OBJECT_free(a->algorithm); - a->algorithm=OBJ_nid2obj(digest->pkey_type); - - - if (!X509_sign(x509,privkey,digest)) - { - long e = ERR_get_error(); - - fprintf(stderr,"SignX509Certificate() Failed: "); - fprintf(stderr," signing Error: %ld\n", e); - - fprintf(stderr,"ERR: %s, %s, %s\n", - ERR_lib_error_string(e), - ERR_func_error_string(e), - ERR_reason_error_string(e)); - - int inl=i2d_X509(x509,NULL); - int outl=EVP_PKEY_size(privkey); - fprintf(stderr,"Size Check: inl: %d, outl: %d\n", inl, outl); - - return NULL; - } - - fprintf(stderr,"SignX509Certificate() Success\n"); - - return x509; -} - +/************************************************************************ + * + * + * CODE IS DIVIDED INTO + * + * 1) SSL Setup. + * 3) Cert Access. + * 4) Cert Sign / Verify. + * 5) Cert Authentication + * 2) Cert Add / Remove + * 6) Cert Storage + */ + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ AuthSSL::AuthSSL() - : p3Config(CONFIG_TYPE_AUTHSSL), init(0), sslctx(NULL), own_private_key(NULL), own_public_key(NULL) + : p3Config(CONFIG_TYPE_AUTHSSL), sslctx(NULL), + mOwnCert(NULL), mOwnPrivateKey(NULL), mOwnPublicKey(NULL), init(0) { } @@ -414,17 +110,6 @@ bool AuthSSL::active() return init; } -// args: server cert, server private key, trusted certificates. - -static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "static verify_x509_callback called."; - std::cerr << std::endl; -#endif - return AuthSSL::getAuthSSL()->VerifyX509Callback(preverify_ok, ctx); - -} int AuthSSL::InitAuth(const char *cert_file, const char *priv_key_file, const char *passwd) @@ -434,6 +119,7 @@ int AuthSSL::InitAuth(const char *cert_file, const char *priv_key_file, std::cerr << std::endl; #endif + /* single call here si don't need to invoke mutex yet */ static int initLib = 0; if (!initLib) { @@ -481,12 +167,6 @@ static int initLib = 0; // get xPGP certificate. X509 *x509 = PEM_read_X509(ownfp, NULL, NULL, NULL); - /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), - * so we do it here then... */ - SSL_CTX *newSslctx = SSL_CTX_new(TLSv1_method()); - SSL_CTX_set_cipher_list(newSslctx, "DEFAULT"); - SSL_CTX_use_certificate(newSslctx, x509); - own_public_key = x509->cert_info->key->pkey; fclose(ownfp); if (x509 == NULL) @@ -496,6 +176,7 @@ static int initLib = 0; return -1; } SSL_CTX_use_certificate(sslctx, x509); + mOwnPublicKey = X509_get_pubkey(x509); // get private key FILE *pkfp = fopen(priv_key_file, "rb"); @@ -506,16 +187,16 @@ static int initLib = 0; return -1; } - own_private_key = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); + mOwnPrivateKey = PEM_read_PrivateKey(pkfp, NULL, NULL, (void *) passwd); fclose(pkfp); - if (own_private_key == NULL) + if (mOwnPrivateKey == NULL) { std::cerr << "AuthSSL::InitAuth() PEM_read_PrivateKey() Failed"; std::cerr << std::endl; return -1; } - SSL_CTX_use_PrivateKey(sslctx, own_private_key); + SSL_CTX_use_PrivateKey(sslctx, mOwnPrivateKey); if (1 != SSL_CTX_check_private_key(sslctx)) { @@ -541,13 +222,14 @@ static int initLib = 0; * for gpg/pgp or CA verification */ - if (!validateOwnCertificate(x509, own_private_key)) + if (!validateOwnCertificate(x509, mOwnPrivateKey)) { std::cerr << "AuthSSL::InitAuth() validateOwnCertificate() Failed"; std::cerr << std::endl; /* bad certificate */ CloseAuth(); + exit(1); return -1; } @@ -569,8 +251,14 @@ static int initLib = 0; /* Dummy function to be overloaded by real implementation */ bool AuthSSL::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey) { + (void) pkey; /* remove unused parameter warning */ + + /* standard authentication */ + if (!AuthX509WithGPG(x509)) + { + return false; + } return true; - //return false; } bool AuthSSL::CloseAuth() @@ -597,51 +285,6 @@ SSL_CTX *AuthSSL::getCTX() return sslctx; } -/* Context handling */ -SSL_CTX *AuthSSL::getNewSslCtx() -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getNewSslCtx()" << 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, own_private_key); - - // 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 - std::cerr << "AuthSSL::setConfigDirectories() "; - std::cerr << " configfile: " << configfile; - std::cerr << " neighdir: " << neighdir; - std::cerr << std::endl; -#endif - RsStackMutex stack(sslMtx); /***** LOCK *****/ - - mCertConfigFile = configfile; - mNeighDir = neighdir; - - return 1; -} - std::string AuthSSL::OwnId() { #ifdef AUTHSSL_DEBUG @@ -657,70 +300,21 @@ std::string AuthSSL::getOwnLocation() #endif return mOwnCert->location; } - - /* Load/Save certificates */ -bool AuthSSL::LoadDetailsFromStringCert(std::string pem, RsPeerDetails &pd) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadIdsFromStringCert() " << std::endl; -#endif - - X509 *x509 = loadX509FromPEM(pem); - if (!x509) { - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadIdsFromStringCert() certificate not loadable (maybe malformed)" << std::endl; - #endif - return false; - } - - if (!ValidateCertificate(x509, pd.id)) { - return false; - } else { - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadIdsFromStringCert() certificate validated." << std::endl; - #endif - - pd.gpg_id = getX509CNString(x509->cert_info->issuer); - pd.location = getX509LocString(x509->cert_info->subject); - return true; - } -} std::string AuthSSL::SaveOwnCertificateToString() { #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::SaveOwnCertificateToString() " << std::endl; #endif - return ConvertCertificateToString(mOwnCert->certificate); + return saveX509ToPEM(mOwnCert->certificate); } -std::string AuthSSL::ConvertCertificateToString(X509* x509) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::ConvertCertificateToString() " << std::endl; -#endif +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ - /* get the cert first */ - std::string certstr; - BIO *bp = BIO_new(BIO_s_mem()); - - PEM_write_bio_X509(bp, x509); - - /* translate the bp data to a string */ - char *data; - int len = BIO_get_mem_data(bp, &data); - for(int i = 0; i < len; i++) - { - certstr += data[i]; - } - - BIO_free(bp); - - return certstr; -} - - /* Sign / Encrypt / Verify Data (TODO) */ - bool AuthSSL::SignData(std::string input, std::string &sign) { return SignData(input.c_str(), input.length(), sign); @@ -732,7 +326,7 @@ bool AuthSSL::SignData(const void *data, const uint32_t len, std::string &sign) RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int signlen = EVP_PKEY_size(own_private_key); + unsigned int signlen = EVP_PKEY_size(mOwnPrivateKey); unsigned char signature[signlen]; if (0 == EVP_SignInit(mdctx, EVP_sha1())) @@ -751,7 +345,7 @@ bool AuthSSL::SignData(const void *data, const uint32_t len, std::string &sign) return false; } - if (0 == EVP_SignFinal(mdctx, signature, &signlen, own_private_key)) + if (0 == EVP_SignFinal(mdctx, signature, &signlen, mOwnPrivateKey)) { std::cerr << "EVP_SignFinal Failure!" << std::endl; @@ -775,7 +369,6 @@ bool AuthSSL::SignData(const void *data, const uint32_t len, std::string &sign) return true; } - bool AuthSSL::SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) { return SignDataBin(input.c_str(), input.length(), sign, signlen); @@ -784,483 +377,61 @@ bool AuthSSL::SignDataBin(std::string input, unsigned char *sign, unsigned int * bool AuthSSL::SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) { - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - unsigned int req_signlen = EVP_PKEY_size(own_private_key); - if (req_signlen > *signlen) - { - /* not enough space */ - std::cerr << "SignDataBin() Not Enough Sign SpacegnInit Failure!" << std::endl; - return false; - } - - 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, sign, signlen, own_private_key)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - return true; + return SSL_SignDataBin(data, len, sign, signlen, mOwnPrivateKey); } -//#define AUTHSSL_DEBUG2 -bool AuthSSL::VerifyOtherSignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, std::string sslCert) { - X509 *x509 = loadX509FromPEM(sslCert); - std::string sslId; - if (!ValidateCertificate(x509, sslId)) { - std::cerr << "AuthSSL::VerifyOtherSignBin() failed to validate certificate." << std::endl; - return false; - } else { - sslcert *cert = new sslcert(x509, sslId); - return VerifySignBin(data, len, sign, signlen, cert); - } - return false; + +bool AuthSSL::VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId) +{ + /* find certificate. + * if we don't have - fail. + */ + + RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ + + /* find the peer */ + sslcert *peer; + if (sslId == mOwnId) + { + peer = mOwnCert; + } + else if (!locked_FindCert(sslId, &peer)) + { + std::cerr << "VerifySignBin() no peer" << std::endl; + return false; + } + + return SSL_VerifySignBin(data, len, sign, signlen, peer->certificate); } bool AuthSSL::VerifyOwnSignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen) { - return VerifySignBin(data, len, sign, signlen, mOwnCert); -} - -bool AuthSSL::VerifySignBin(const void *data, const uint32_t len, - unsigned char *sign, unsigned int signlen, sslcert* peer) + unsigned char *sign, unsigned int signlen) { - - RsStackMutex stack(sslMtx); /***** STACK LOCK MUTEX *****/ - - /* find the peer */ -#ifdef AUTHSSL_DEBUG2 - std::cerr << "In AuthSSL::VerifySignBin" << std::endl; -#endif - - //std::cerr << "Cert info : " << getX509Info(X509 *cert) << std::endl; - - /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), - * so we do it here then... */ - SSL_CTX *newSslctx = SSL_CTX_new(TLSv1_method()); - SSL_CTX_set_cipher_list(newSslctx, "DEFAULT"); - SSL_CTX_use_certificate(newSslctx, peer->certificate); - - - EVP_PKEY *peerkey = peer->certificate->cert_info->key->pkey; - - if(peerkey == NULL) - { -#ifdef AUTHSSL_DEBUG2 - std::cerr << "AuthSSL::VerifySignBin: no public key available !!" << std::endl ; -#endif - return false ; - } - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - if (0 == EVP_VerifyInit(mdctx, EVP_sha1())) - { - std::cerr << "EVP_VerifyInit Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - X509_free(peer->certificate); - return false; - } - - if (0 == EVP_VerifyUpdate(mdctx, data, len)) - { - std::cerr << "EVP_VerifyUpdate Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - X509_free(peer->certificate); - return false; - } - - if(signlen == 0 || sign == NULL) - { -#ifdef AUTHSSL_DEBUG2 - std::cerr << "AuthSSL::VerifySignBin: signlen=" << signlen << ", sign=" << (void*)sign << "!!" << std::endl ; -#endif - EVP_MD_CTX_destroy(mdctx); - X509_free(peer->certificate); - return false ; - } - - if (0 == EVP_VerifyFinal(mdctx, sign, signlen, peerkey)) - { - std::cerr << "EVP_VerifyFinal Failure!" << std::endl; - - EVP_MD_CTX_destroy(mdctx); - X509_free(peer->certificate); - return false; - } - - EVP_MD_CTX_destroy(mdctx); - X509_free(peer->certificate); - return true; + return SSL_VerifySignBin(data, len, sign, signlen, mOwnCert->certificate); } -X509 *AuthSSL::loadX509FromFile(std::string fname, std::string hash) + +/********************************************************************************/ +/********************************************************************************/ +/********************* Sign and Auth with GPG **************************/ +/********************************************************************************/ +/********************************************************************************/ + +/* Note these functions don't need Mutexes - + * only using GPG functions - which lock themselves + */ + +X509 *AuthSSL::SignX509ReqWithGPG(X509_REQ *req, long days) { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadX509FromFile()"; - std::cerr << std::endl; -#endif - - // if there is a hash - check that the file matches it before loading. - X509 *pc = NULL; - FILE *pcertfp = fopen(fname.c_str(), "rb"); - - // load certificates from file. - if (pcertfp == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "sslroot::loadcertificate() Bad File: " << fname; - std::cerr << " Cannot be Hashed!" << std::endl; -#endif - return NULL; - } - - /* We only check a signature's hash if - * we are loading from a configuration file. - * Therefore we saved the file and it should be identical. - * and a direct load + verify will work. - * - * If however it has been transported by email.... - * Then we might have to correct the data (strip out crap) - * from the configuration at the end. (X509 load should work!) - */ - - if (hash.length() > 1) - { - - unsigned int signlen = EVP_PKEY_size(own_private_key); - unsigned char signature[signlen]; - - int maxsize = 20480; /* should be enough for about 50 signatures */ - int rbytes; - char inall[maxsize]; - if (0 == (rbytes = fread(inall, 1, maxsize, pcertfp))) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "Error Reading Peer Record!" << std::endl; -#endif - return NULL; - } - //std::cerr << "Read " << rbytes << std::endl; - - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - if (0 == EVP_SignInit_ex(mdctx, EVP_sha1(), NULL)) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - } - - if (0 == EVP_SignUpdate(mdctx, inall, rbytes)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - } - - if (0 == EVP_SignFinal(mdctx, signature, &signlen, own_private_key)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - } - - EVP_MD_CTX_destroy(mdctx); - - bool same = true; - if (signlen != hash.length()) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "Different Length Signatures... "; - std::cerr << "Cannot Load Certificate!" << std::endl; -#endif - fclose(pcertfp); - return NULL; - } - - for(int i = 0; i < (signed) signlen; i++) - { - if (signature[i] != (unsigned char) hash[i]) - { - same = false; -#ifdef AUTHSSL_DEBUG - std::cerr << "Invalid Signature... "; - std::cerr << "Cannot Load Certificate!" << std::endl; -#endif - fclose(pcertfp); - return NULL; - } - } -#ifdef AUTHSSL_DEBUG - std::cerr << "Verified Signature for: " << fname; - std::cerr << std::endl; -#endif - } - else - { -#ifdef AUTHSSL_DEBUG - std::cerr << "Not checking cert signature" << std::endl; -#endif - } - - fseek(pcertfp, 0, SEEK_SET); /* rewind */ - pc = PEM_read_X509(pcertfp, NULL, NULL, NULL); - fclose(pcertfp); - - if (pc != NULL) - { - // read a certificate. -#ifdef AUTHSSL_DEBUG - std::cerr << "Loaded Certificate: " << pc -> name << std::endl; -#endif - } - else // (pc == NULL) - { - unsigned long err = ERR_get_error(); - std::cerr << "Read Failed .... CODE(" << err << ")" << std::endl; - std::cerr << ERR_error_string(err, NULL) << std::endl; - - return NULL; - } - return pc; -} - -bool AuthSSL::saveX509ToFile(X509 *x509, std::string fname, std::string &hash) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::saveX509ToFile()"; - std::cerr << std::endl; -#endif - - // load certificates from file. - FILE *setfp = fopen(fname.c_str(), "wb"); - if (setfp == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "sslroot::savecertificate() Bad File: " << fname; - std::cerr << " Cannot be Written!" << std::endl; -#endif - return false; - } - -#ifdef AUTHSSL_DEBUG - std::cerr << "Writing out Cert...:" << x509->name << std::endl; -#endif - PEM_write_X509(setfp, x509); - - fclose(setfp); - - // then reopen to generate hash. - setfp = fopen(fname.c_str(), "rb"); - if (setfp == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "sslroot::savecertificate() Bad File: " << fname; - std::cerr << " Opened for ReHash!" << std::endl; -#endif - return false; - } - - unsigned int signlen = EVP_PKEY_size(own_private_key); - unsigned char signature[signlen]; - - int maxsize = 20480; - int rbytes; - char inall[maxsize]; - if (0 == (rbytes = fread(inall, 1, maxsize, setfp))) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "Error Writing Peer Record!" << std::endl; -#endif - return -1; - } -#ifdef AUTHSSL_DEBUG - std::cerr << "Read " << rbytes << std::endl; -#endif - - EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); - - if (0 == EVP_SignInit_ex(mdctx, EVP_sha1(), NULL)) - { - std::cerr << "EVP_SignInit Failure!" << std::endl; - } - - if (0 == EVP_SignUpdate(mdctx, inall, rbytes)) - { - std::cerr << "EVP_SignUpdate Failure!" << std::endl; - } - - if (0 == EVP_SignFinal(mdctx, signature, &signlen, own_private_key)) - { - std::cerr << "EVP_SignFinal Failure!" << std::endl; - } - -#ifdef AUTHSSL_DEBUG - std::cerr << "Saved Cert: " << x509->name; - std::cerr << std::endl; -#endif - -#ifdef AUTHSSL_DEBUG - std::cerr << "Cert + Setting Signature is(" << signlen << "): "; -#endif - std::string signstr; - for(uint32_t i = 0; i < signlen; i++) - { -#ifdef AUTHSSL_DEBUG - fprintf(stderr, "%02x", signature[i]); -#endif - signstr += signature[i]; - } -#ifdef AUTHSSL_DEBUG - std::cerr << std::endl; -#endif - - hash = signstr; - fclose(setfp); - - EVP_MD_CTX_destroy(mdctx); - - return true; -} - - -X509 *AuthSSL::loadX509FromPEM(std::string pem) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadX509FromPEM()"; - std::cerr << std::endl; -#endif - - /* Put the data into a mem BIO */ - char *certstr = strdup(pem.c_str()); - - BIO *bp = BIO_new_mem_buf(certstr, -1); - - X509 *pc = PEM_read_bio_X509(bp, NULL, NULL, NULL); - - BIO_free(bp); - free(certstr); - - return pc; -} - -X509 *AuthSSL::loadX509FromDER(const uint8_t *ptr, uint32_t len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LoadX509FromDER()"; - std::cerr << std::endl; -#endif - - X509 *tmp = NULL; -#ifdef __APPLE__ - unsigned char **certptr = (unsigned char **) &ptr; -#else - const unsigned char **certptr = (const unsigned char **) &ptr; -#endif - - X509 *x509 = d2i_X509(&tmp, certptr, len); - - return x509; -} - -bool AuthSSL::saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len) -{ -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::saveX509ToDER()"; - std::cerr << std::endl; -#endif - - int certlen = i2d_X509(x509, (unsigned char **) ptr); - if (certlen > 0) - { - *len = certlen; - return true; - } - else - { - *len = 0; - return false; - } - return false; -} - - -bool getX509id(X509 *x509, std::string &xid) { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id()"; - std::cerr << std::endl; -#endif - - xid = ""; - if (x509 == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() NULL pointer"; - std::cerr << std::endl; -#endif - return false; - } - - // get the signature from the cert, and copy to the array. - ASN1_BIT_STRING *signature = x509->signature; - int signlen = ASN1_STRING_length(signature); - if (signlen < CERTSIGNLEN) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; - std::cerr << std::endl; -#endif - return false; - } - - // else copy in the first CERTSIGNLEN. - unsigned char *signdata = ASN1_STRING_data(signature); - - std::ostringstream id; - /* switched to the other end of the signature. for - * more randomness - */ - for(int i = signlen - CERTSIGNLEN; i < signlen; i++) - { - id << std::hex << std::setw(2) << std::setfill('0') - << (uint16_t) (((uint8_t *) (signdata))[i]); - } - xid = id.str(); - return true; -} - -X509 *AuthSSL::SignX509Req(X509_REQ *req, long days) -{ - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - /* Transform the X509_REQ into a suitable format to * generate DIGEST hash. (for SSL to do grunt work) */ - #define SERIAL_RAND_BITS 64 - const EVP_MD *digest = EVP_sha1(); + //const EVP_MD *digest = EVP_sha1(); ASN1_INTEGER *serial = ASN1_INTEGER_new(); EVP_PKEY *tmppkey; X509 *x509 = X509_new(); @@ -1270,7 +441,7 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days) return NULL; } - long version = 0x00; + //long version = 0x00; unsigned long chtype = MBSTRING_ASC; X509_NAME *issuer_name = X509_NAME_new(); X509_NAME_add_entry_by_txt(issuer_name, "CN", chtype, @@ -1351,13 +522,13 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days) X509_ALGOR *algor2 = x509->sig_alg; ASN1_BIT_STRING *signature = x509->signature; X509_CINF *data = x509->cert_info; - EVP_PKEY *pkey = NULL; + //EVP_PKEY *pkey = NULL; const EVP_MD *type = EVP_sha1(); EVP_MD_CTX ctx; unsigned char *p,*buf_in=NULL; unsigned char *buf_hashout=NULL,*buf_sigout=NULL; - int i,inl=0,hashoutl=0,hashoutll=0; + int inl=0,hashoutl=0,hashoutll=0; int sigoutl=0,sigoutll=0; X509_ALGOR *a; @@ -1451,7 +622,7 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days) return x509; - + /* XXX CLEANUP */ err: /* cleanup */ std::cerr << "GPGAuthMgr::SignX509Req() err: FAIL" << std::endl; @@ -1459,13 +630,23 @@ X509 *AuthSSL::SignX509Req(X509_REQ *req, long days) return NULL; } -bool AuthSSL::AuthX509(X509 *x509) + +/* This function, checks that the X509 is signed by a known GPG key, + * NB: we do not have to have approved this person as a friend. + * this is important - as it allows non-friends messages to be validated. + */ + +bool AuthSSL::AuthX509WithGPG(X509 *x509) { #ifdef AUTHSSL_DEBUG - fprintf(stderr, "AuthSSL::AuthX509() called\n"); + fprintf(stderr, "AuthSSL::AuthX509WithGPG() called\n"); #endif - //RsStackMutex stack(sslMtx); /******* LOCKED ******/ + if (!CheckX509Certificate(x509)) + { + std::cerr << "AuthSSL::AuthX509() X509 NOT authenticated : Certificate failed basic checks" << std::endl; + return false; + } /* extract CN for peer Id */ std::string issuer = getX509CNString(x509->cert_info->issuer); @@ -1489,9 +670,9 @@ bool AuthSSL::AuthX509(X509 *x509) EVP_MD_CTX ctx; unsigned char *p,*buf_in=NULL; unsigned char *buf_hashout=NULL,*buf_sigout=NULL; - int i,inl=0,hashoutl=0,hashoutll=0; + int inl=0,hashoutl=0,hashoutll=0; int sigoutl=0,sigoutll=0; - X509_ALGOR *a; + //X509_ALGOR *a; EVP_MD_CTX_init(&ctx); @@ -1558,24 +739,24 @@ bool AuthSSL::AuthX509(X509 *x509) goto err; } - #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::AuthX509() X509 authenticated" << std::endl; #endif - LocalStoreCert(x509); - return true; err: std::cerr << "AuthSSL::AuthX509() X509 NOT authenticated" << std::endl; return false; } + + + /* validate + get id */ bool AuthSSL::ValidateCertificate(X509 *x509, std::string &peerId) { /* check self signed */ - if (!AuthX509(x509)) + if (!AuthX509WithGPG(x509)) { #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::ValidateCertificate() bad certificate."; @@ -1600,23 +781,135 @@ bool AuthSSL::ValidateCertificate(X509 *x509, std::string &peerId) return true; } -/* store for discovery */ -bool AuthSSL::FailedCertificate(X509 *x509, bool incoming) + +/********************************************************************************/ +/********************************************************************************/ +/**************************** encrypt / decrypt fns ****************************/ +/********************************************************************************/ +/********************************************************************************/ + +static int verify_x509_callback(int preverify_ok, X509_STORE_CTX *ctx) { - //std::string id; - //return ProcessX509(x509, id); - return true; +#ifdef AUTHSSL_DEBUG + std::cerr << "static verify_x509_callback called."; + std::cerr << std::endl; +#endif + return AuthSSL::getAuthSSL()->VerifyX509Callback(preverify_ok, ctx); + } -bool AuthSSL::CheckCertificate(std::string id, X509 *x509) +int AuthSSL::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) { - //std::string id; - //return ProcessX509(x509, id); - return true; + char buf[256]; + X509 *err_cert; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::VerifyX509Callback(preverify_ok: " << preverify_ok + << " Err: " << err << " Depth: " << depth << std::endl; + #endif + + /* + * Retrieve the pointer to the SSL of the connection currently treated + * and the application specific data stored into the SSL object. + */ + + X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); + + #ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::VerifyX509Callback: depth: " << depth << ":" << buf << std::endl; + #endif + + + if (!preverify_ok) { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "Verify error:num=%d:%s:depth=%d:%s\n", err, + X509_verify_cert_error_string(err), depth, buf); + #endif + } + + /* + * At this point, err contains the last verification error. We can use + * it for something special + */ + + if (!preverify_ok) + { + + X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256); + #ifdef AUTHSSL_DEBUG + printf("issuer= %s\n", buf); + #endif + + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "Doing REAL PGP Certificates\n"); + #endif + /* do the REAL Authentication */ + if (!AuthX509WithGPG(X509_STORE_CTX_get_current_cert(ctx))) + { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "AuthSSL::VerifyX509Callback() X509 not authenticated.\n"); + #endif + return false; + } + std::string pgpid = getX509CNString(X509_STORE_CTX_get_current_cert(ctx)->cert_info->issuer); + if (!AuthGPG::getAuthGPG()->isGPGAccepted(pgpid)) + { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "AuthSSL::VerifyX509Callback() pgp key not accepted : \n"); + fprintf(stderr, "issuer pgpid : "); + fprintf(stderr, "%s\n",pgpid.c_str()); + fprintf(stderr, "\n AuthGPG::getAuthGPG()->getGPGOwnId() : "); + fprintf(stderr, "%s\n",AuthGPG::getAuthGPG()->getGPGOwnId().c_str()); + fprintf(stderr, "\n"); + #endif + return false; + } + + preverify_ok = true; + + } else { + #ifdef AUTHSSL_DEBUG + fprintf(stderr, "A normal certificate is probably a security breach attempt. We sould fail it !!!\n"); + #endif + preverify_ok = false; + } + + if (preverify_ok) { + + //sslcert *cert = NULL; + std::string certId; + getX509id(X509_STORE_CTX_get_current_cert(ctx), certId); + + } + + #ifdef AUTHSSL_DEBUG + if (preverify_ok) { + fprintf(stderr, "AuthSSL::VerifyX509Callback returned true.\n"); + } else { + fprintf(stderr, "AuthSSL::VerifyX509Callback returned false.\n"); + } + #endif + + return preverify_ok; } + +/********************************************************************************/ +/********************************************************************************/ +/**************************** encrypt / decrypt fns ****************************/ +/********************************************************************************/ +/********************************************************************************/ + + bool AuthSSL::encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId) { + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::encrypt() called for peerId : " << peerId << " with inlen : " << inlen << std::endl; #endif @@ -1627,7 +920,7 @@ bool AuthSSL::encrypt(void *&out, int &outlen, const void *in, int inlen, std EVP_PKEY *public_key; if (peerId == mOwnId) { - public_key = own_public_key; + public_key = mOwnPublicKey; } else { if (!mCerts[peerId]) { #ifdef AUTHSSL_DEBUG @@ -1719,6 +1012,10 @@ bool AuthSSL::encrypt(void *&out, int &outlen, const void *in, int inlen, std bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen) { + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + + #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::decrypt() called with inlen : " << inlen << std::endl; #endif @@ -1743,7 +1040,7 @@ bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen) ekeylen = ntohl(ekeylen); - if (ekeylen != EVP_PKEY_size(own_private_key)) + if (ekeylen != (unsigned) EVP_PKEY_size(mOwnPrivateKey)) { fprintf(stderr, "keylength mismatch"); return false; @@ -1771,7 +1068,7 @@ bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen) EVP_CIPHER_CTX_init(&ectx); if(!EVP_DecryptInit_ex(&ectx,EVP_aes_256_cbc(),NULL, NULL,NULL)) return false; - if (own_private_key->type != EVP_PKEY_RSA) + if (mOwnPrivateKey->type != EVP_PKEY_RSA) { return false; } @@ -1783,9 +1080,9 @@ bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen) } #if OPENSSL_VERSION_NUMBER >= 0x10000000L - i=EVP_PKEY_decrypt_old(key,encryptKey,ekeylen,own_private_key); + i=EVP_PKEY_decrypt_old(key,encryptKey,ekeylen,mOwnPrivateKey); #else - i=EVP_PKEY_decrypt(key,encryptKey,ekeylen,own_private_key); + i=EVP_PKEY_decrypt(key,encryptKey,ekeylen,mOwnPrivateKey); #endif if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(&ectx, i)) { @@ -1821,10 +1118,142 @@ bool AuthSSL::decrypt(void *&out, int &outlen, const void *in, int inlen) return true; } -// -----------------------------------------------------------------------------------// -// -------------------------------- Config functions ------------------------------ // -// -----------------------------------------------------------------------------------// -// + +/********************************************************************************/ +/********************************************************************************/ +/********************* Cert Search / Add / Remove **************************/ +/********************************************************************************/ +/********************************************************************************/ + +/* store for discovery */ +bool AuthSSL::FailedCertificate(X509 *x509, bool incoming) +{ + (void) incoming; /* remove unused parameter warning */ + + /* if auths -> store */ + if (AuthX509WithGPG(x509)) + { + LocalStoreCert(x509); + return true; + } + return false; +} + +bool AuthSSL::CheckCertificate(std::string id, X509 *x509) +{ + (void) id; /* remove unused parameter warning */ + + /* if auths -> store */ + if (AuthX509WithGPG(x509)) + { + LocalStoreCert(x509); + return true; + } + return false; +} + + + +/* Locked search -> internal help function */ +bool AuthSSL::locked_FindCert(std::string id, sslcert **cert) +{ + std::map::iterator it; + + if (mCerts.end() != (it = mCerts.find(id))) + { + *cert = it->second; + return true; + } + return false; +} + + +/* Remove Certificate */ + +bool AuthSSL::RemoveX509(std::string id) +{ + std::map::iterator it; + + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + if (mCerts.end() != (it = mCerts.find(id))) + { + sslcert *cert = it->second; + + /* clean up */ + X509_free(cert->certificate); + cert->certificate = NULL; + delete cert; + + mCerts.erase(it); + + return true; + } + return false; +} + + +bool AuthSSL::LocalStoreCert(X509* x509) +{ + //store the certificate in the local cert list + std::string peerId; + if(!getX509id(x509, peerId)) + { + std::cerr << "AuthSSL::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl; +#ifdef AUTHSSL_DEBUG +#endif + return false; + } + + + RsStackMutex stack(sslMtx); /******* LOCKED ******/ + + if (peerId == mOwnId) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::LocalStoreCert() not storing own certificate" << std::endl; +#endif + return false; + } + + /* do a search */ + std::map::iterator it; + + if (mCerts.end() != (it = mCerts.find(peerId))) + { + sslcert *cert = it->second; + + /* found something */ + /* check that they are exact */ + if (0 != X509_cmp(cert->certificate, x509)) + { + /* MAJOR ERROR */ + std::cerr << "ERROR : AuthSSL::LocalStoreCert() got two ssl certificates with identical ids -> dropping second"; + std::cerr << std::endl; + return false; + } + /* otherwise - we have it already */ + return false; + } + +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::LocalStoreCert() storing certificate for " << peerId << std::endl; +#endif + mCerts[peerId] = new sslcert(X509_dup(x509), peerId); + + /* flag for saving config */ + IndicateConfigChanged(); + return true ; +} + + +/********************************************************************************/ +/********************************************************************************/ +/************************ Config Functions **********************************/ +/********************************************************************************/ +/********************************************************************************/ + + RsSerialiser *AuthSSL::setupSerialiser() { RsSerialiser *rss = new RsSerialiser ; @@ -1856,7 +1285,7 @@ std::list AuthSSL::saveList(bool& cleanup) #ifdef AUTHSSL_DEBUG std::cerr << "AuthSSL::saveList() called (mapIt->first) : " << (mapIt->first) << std::endl ; #endif - kv.value = ConvertCertificateToString(mapIt->second->certificate); + kv.value = saveX509ToPEM(mapIt->second->certificate); vitem->tlvkvs.pairs.push_back(kv) ; } lst.push_back(vitem); @@ -1887,9 +1316,13 @@ bool AuthSSL::loadList(std::list load) if (kit->key == mOwnId) { continue; } - //authenticate the certificate will store it in the mCerts map - RsPeerDetails pd; - LoadDetailsFromStringCert(kit->value, pd); + + X509 *peer = loadX509FromPEM(kit->value); + /* authenticate it */ + if (AuthX509WithGPG(peer)) + { + LocalStoreCert(peer); + } } } delete (*it); @@ -1903,491 +1336,3 @@ bool AuthSSL::loadList(std::list load) /********************************************************************************/ /********************************************************************************/ -int pem_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - strncpy(buf, (char *)(password), size); - buf[size - 1] = '\0'; - return(strlen(buf)); -} - -bool AuthSSL::LocalStoreCert(X509* x509) -{ - //store the certificate in the local cert list - std::string peerId; - if(!getX509id(x509, peerId)) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl; -#endif - return false; - } - if (peerId != mOwnId) - { - if (mCerts[peerId]) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LocalStoreCert() get duplicate for " << mCerts[peerId]->id << std::endl; -#endif - /* have a duplicate */ - /* check that they are exact */ - if (0 != X509_cmp(mCerts[peerId]->certificate, x509)) - { - /* MAJOR ERROR */ - std::cerr << "ERROR : AuthSSL::ValidateCertificate() got two different ssl certificate from the same peer. It could be a security intrusion attempt (man in the middle)."; - std::cerr << std::endl; - return false; - } - } - else - { - RsStackMutex stack(sslMtx); /******* LOCKED ******/ - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LocalStoreCert() storing certificate for " << peerId << std::endl; -#endif - //have a deep copy of the x509 cert - BIO *bp = BIO_new(BIO_s_mem()); - PEM_write_bio_X509(bp, x509); - X509 *certCopy = PEM_read_bio_X509(bp, NULL, 0, NULL); - - mCerts[peerId] = new sslcert(certCopy, peerId); - /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(), - * so we do it here then... */ - SSL_CTX *newSslctx = SSL_CTX_new(TLSv1_method()); - SSL_CTX_set_cipher_list(newSslctx, "DEFAULT"); - SSL_CTX_use_certificate(newSslctx, mCerts[peerId]->certificate); - -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LocalStoreCert() storing certificate with public key : " << mCerts[peerId]->certificate->cert_info->key->pkey << std::endl; -#endif - - IndicateConfigChanged(); - } - } else { -#ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::LocalStoreCert() not storing certificate because it's our own " << peerId << std::endl; -#endif - } - - return true ; -} - -int AuthSSL::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx) -{ - char buf[256]; - X509 *err_cert; - int err, depth; - - err_cert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); - depth = X509_STORE_CTX_get_error_depth(ctx); - - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::VerifyX509Callback(preverify_ok: " << preverify_ok - << " Err: " << err << " Depth: " << depth << std::endl; - #endif - - /* - * Retrieve the pointer to the SSL of the connection currently treated - * and the application specific data stored into the SSL object. - */ - - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); - - #ifdef AUTHSSL_DEBUG - std::cerr << "AuthSSL::VerifyX509Callback: depth: " << depth << ":" << buf << std::endl; - #endif - - - if (!preverify_ok) { - #ifdef AUTHSSL_DEBUG - fprintf(stderr, "Verify error:num=%d:%s:depth=%d:%s\n", err, - X509_verify_cert_error_string(err), depth, buf); - #endif - } - - /* - * At this point, err contains the last verification error. We can use - * it for something special - */ - - if (!preverify_ok) - { - - X509_NAME_oneline(X509_get_issuer_name(X509_STORE_CTX_get_current_cert(ctx)), buf, 256); - #ifdef AUTHSSL_DEBUG - printf("issuer= %s\n", buf); - #endif - - #ifdef AUTHSSL_DEBUG - fprintf(stderr, "Doing REAL PGP Certificates\n"); - #endif - /* do the REAL Authentication */ - if (!AuthX509(X509_STORE_CTX_get_current_cert(ctx))) - { - #ifdef AUTHSSL_DEBUG - fprintf(stderr, "AuthSSL::VerifyX509Callback() X509 not authenticated.\n"); - #endif - return false; - } - std::string pgpid = getX509CNString(X509_STORE_CTX_get_current_cert(ctx)->cert_info->issuer); - if (!AuthGPG::getAuthGPG()->isGPGAccepted(pgpid) && pgpid != AuthGPG::getAuthGPG()->getGPGOwnId()) - { - #ifdef AUTHSSL_DEBUG - fprintf(stderr, "AuthSSL::VerifyX509Callback() pgp key not accepted : \n"); - fprintf(stderr, "issuer pgpid : "); - fprintf(stderr, "%s\n",pgpid.c_str()); - fprintf(stderr, "\n AuthGPG::getAuthGPG()->getGPGOwnId() : "); - fprintf(stderr, "%s\n",AuthGPG::getAuthGPG()->getGPGOwnId().c_str()); - fprintf(stderr, "\n"); - #endif - return false; - } - - preverify_ok = true; - - } else { - #ifdef AUTHSSL_DEBUG - fprintf(stderr, "A normal certificate is probably a security breach attempt. We sould fail it !!!\n"); - #endif - preverify_ok = false; - } - - if (preverify_ok) { - - //sslcert *cert = NULL; - std::string certId; - getX509id(X509_STORE_CTX_get_current_cert(ctx), certId); - - } - - #ifdef AUTHSSL_DEBUG - if (preverify_ok) { - fprintf(stderr, "AuthSSL::VerifyX509Callback returned true.\n"); - } else { - fprintf(stderr, "AuthSSL::VerifyX509Callback returned false.\n"); - } - #endif - - return preverify_ok; -} - - -// Not dependent on sslroot. load, and detroys the X509 memory. - -int LoadCheckX509andGetLocation(const char *cert_file, std::string &location, std::string &userId) -{ - /* This function loads the X509 certificate from the file, - * and checks the certificate - */ - - FILE *tmpfp = fopen(cert_file, "r"); - if (tmpfp == NULL) - { - std::cerr << "sslroot::LoadCheckAndGetX509Name()"; - std::cerr << " Failed to open Certificate File:" << cert_file; - std::cerr << std::endl; - return 0; - } - - // get xPGP certificate. - X509 *x509 = PEM_read_X509(tmpfp, NULL, NULL, NULL); - fclose(tmpfp); - - if(x509 == NULL) - { - std::cerr << "PEM_read_X509 failed !!" << std::endl ; - return false ; - } - - // check the certificate. - // - - if (AuthSSL::getAuthSSL()->ValidateCertificate(x509, userId)) - location = getX509LocString(x509->cert_info->subject); - else - { - std::cerr << "certificate validation failed !!" << std::endl ; - return false ; - } - - #ifdef AUTHSSL_DEBUG - std::cerr << "getX509LocString ok. Info:" << std::endl ; - std::cout << getX509Info(x509) << std::endl ; - #endif - // clean up. - X509_free(x509); - - return true ; -} - - -// Not dependent on sslroot. load, and detroys the X509 memory. - -int LoadCheckX509andGetIssuerName(const char *cert_file, std::string &issuerName, std::string &userId) -{ - /* This function loads the X509 certificate from the file, - * and checks the certificate - */ - - FILE *tmpfp = fopen(cert_file, "r"); - if (tmpfp == NULL) - { -#ifdef AUTHSSL_DEBUG - std::cerr << "sslroot::LoadCheckAndGetX509Name()"; - std::cerr << " Failed to open Certificate File:" << cert_file; - std::cerr << std::endl; -#endif - return 0; - } - - // get xPGP certificate. - X509 *x509 = PEM_read_X509(tmpfp, NULL, NULL, NULL); - fclose(tmpfp); - - // check the certificate. - bool valid = false; - if (x509) - { - valid = AuthSSL::getAuthSSL()->ValidateCertificate(x509, userId); - } - - if (valid) - { - // extract the name. - issuerName = getX509CNString(x509->cert_info->issuer); - } - - #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; - } -} - -std::string getX509NameString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - namestr += "\t"; - namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); - namestr += " : "; - - //namestr += entry_obj -> flags; - //namestr += entry_data -> length; - //namestr += entry_data -> type; - - //namestr += entry_data -> flags; - //entry -> set; - - if (entry_data -> data != NULL) - { - namestr += (char *) entry_data -> data; - } - else - { - namestr += "NULL"; - } - - if (i + 1 < X509_NAME_entry_count(name)) - { - namestr += "\n"; - } - - } - return namestr; -} - - -std::string getX509CNString(X509_NAME *name) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) - { - if (entry_data -> data != NULL) - { - namestr += (char *) entry_data -> data; - } - else - { - namestr += "Unknown"; - } - return namestr; - } - } - return namestr; -} - - -std::string getX509TypeString(X509_NAME *name, const char *type, int len) -{ - std::string namestr; - for(int i = 0; i < X509_NAME_entry_count(name); i++) - { - X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); - ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); - ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); - - if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) - { - if (entry_data -> data != NULL) - { - namestr += (char *) entry_data -> data; - } - else - { - namestr += "Unknown"; - } - return namestr; - } - } - return namestr; -} - - -std::string getX509LocString(X509_NAME *name) -{ - return getX509TypeString(name, "L", 2); -} - -std::string getX509OrgString(X509_NAME *name) -{ - return getX509TypeString(name, "O", 2); -} - - -std::string getX509CountryString(X509_NAME *name) -{ - return getX509TypeString(name, "C", 2); -} - - -std::string getX509Info(X509 *cert) -{ - std::stringstream out; - long l; - - out << "X509 Certificate:" << std::endl; - l=X509_get_version(cert); - out << " Version: " << l+1 << "(0x" << l << ")" << std::endl; - out << " Subject: " << std::endl; - out << " " << getX509NameString(cert->cert_info->subject); - out << std::endl; - out << std::endl; - out << " Signatures:" << std::endl; - return out.str(); -} - - - -std::string getX509AuthCode(X509 *x509) -{ - /* get the self signature -> the first signature */ - - std::stringstream out; - - ASN1_BIT_STRING *signature = x509->signature; - int signlen = ASN1_STRING_length(signature); - unsigned char *signdata = ASN1_STRING_data(signature); - - /* extract the authcode from the signature */ - /* convert it to a string, inverse of 2 bytes of signdata */ - if (signlen > 2) - signlen = 2; - int j; - for(j=0;jcert_info->subject); - // strip out bad chars. - for(int i = 0; i < (signed) name.length(); i++) - { - if ((name[i] == '/') || (name[i] == ' ') || (name[i] == '=') || - (name[i] == '\\') || (name[i] == '\t') || (name[i] == '\n')) - { - name[i] = '_'; - } - } - return name; -} - -/********** SSL ERROR STUFF ******************************************/ - -int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, - std::ostream &out) -{ - std::string reason; - - std::string mainreason = std::string("UNKNOWN ERROR CODE"); - if (err == SSL_ERROR_NONE) - { - mainreason = std::string("SSL_ERROR_NONE"); - } - else if (err == SSL_ERROR_ZERO_RETURN) - { - mainreason = std::string("SSL_ERROR_ZERO_RETURN"); - } - else if (err == SSL_ERROR_WANT_READ) - { - mainreason = std::string("SSL_ERROR_WANT_READ"); - } - else if (err == SSL_ERROR_WANT_WRITE) - { - mainreason = std::string("SSL_ERROR_WANT_WRITE"); - } - else if (err == SSL_ERROR_WANT_CONNECT) - { - mainreason = std::string("SSL_ERROR_WANT_CONNECT"); - } - else if (err == SSL_ERROR_WANT_ACCEPT) - { - mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); - } - else if (err == SSL_ERROR_WANT_X509_LOOKUP) - { - mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); - } - else if (err == SSL_ERROR_SYSCALL) - { - mainreason = std::string("SSL_ERROR_SYSCALL"); - } - else if (err == SSL_ERROR_SSL) - { - mainreason = std::string("SSL_ERROR_SSL"); - } - out << "RetVal(" << retval; - out << ") -> SSL Error: " << mainreason << std::endl; - out << "\t + ERR Error: " << ERR_error_string(err2, NULL) << std::endl; - return 1; -} diff --git a/libretroshare/src/pqi/authssl.h b/libretroshare/src/pqi/authssl.h index 4b251bd41..e0f6c5f2c 100644 --- a/libretroshare/src/pqi/authssl.h +++ b/libretroshare/src/pqi/authssl.h @@ -99,9 +99,6 @@ virtual bool active(); 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 **********/ @@ -120,51 +117,32 @@ virtual std::string getOwnLocation(); //virtual std::string getGPGId(SSL_id id); //virtual bool getCertDetails(std::string id, sslcert &cert); - /* High Level Load/Save Configuration */ -//virtual bool FinalSaveCertificates(); -//virtual bool CheckSaveCertificates(); -//virtual bool saveCertificates(); -//virtual bool loadCertificates(); - /* Load/Save certificates */ - -virtual bool LoadDetailsFromStringCert(std::string pem, RsPeerDetails &pd); virtual std::string SaveOwnCertificateToString(); -virtual std::string ConvertCertificateToString(X509* x509); -//virtual bool LoadCertificateFromFile(std::string filename, std::string &id); -//virtual bool SaveCertificateToFile(std::string id, std::string filename); -//bool ProcessX509(X509 *x509, std::string &id); -// -//virtual bool LoadCertificateFromBinary(const uint8_t *ptr, uint32_t len, std::string &id); -//virtual bool SaveCertificateToBinary(std::string id, uint8_t **ptr, uint32_t *len); - /* Sign / Encrypt / Verify Data (TODO) */ -virtual bool SignData(std::string input, std::string &sign); -virtual bool SignData(const void *data, const uint32_t len, std::string &sign); -virtual bool SignDataBin(std::string, unsigned char*, unsigned int*); -virtual bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*); -virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, sslcert* cert); -virtual bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int); -virtual bool VerifyOtherSignBin(const void*, uint32_t, unsigned char*, unsigned int, std::string sslCert); + /* Sign / Encrypt / Verify Data */ +bool SignData(std::string input, std::string &sign); +bool SignData(const void *data, const uint32_t len, std::string &sign); + +bool SignDataBin(std::string, unsigned char*, unsigned int*); +bool SignDataBin(const void*, uint32_t, unsigned char*, unsigned int*); +bool VerifyOwnSignBin(const void*, uint32_t, unsigned char*, unsigned int); +bool VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, SSL_id sslId); // return : false if encrypt failed bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string peerId); - // return : false if decrypt fails bool decrypt(void *&out, int &outlen, const void *in, int inlen); - /*********** Overloaded Functions from p3AuthMgr **********/ - - /************* Virtual Functions from AuthSSL *************/ -X509* SignX509Req(X509_REQ *req, long days); -bool AuthX509(X509 *x509); +X509* SignX509ReqWithGPG(X509_REQ *req, long days); +bool AuthX509WithGPG(X509 *x509); -virtual int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx); -virtual bool ValidateCertificate(X509 *x509, std::string &peerId); /* validate + get id */ +int VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx); +bool ValidateCertificate(X509 *x509, std::string &peerId); /* validate + get id */ - /************* Virtual Functions from AuthSSL *************/ /*****************************************************************/ /*********************** p3config ******************************/ @@ -181,9 +159,6 @@ SSL_CTX *getCTX(); bool FailedCertificate(X509 *x509, bool incoming); /* store for discovery */ bool CheckCertificate(std::string peerId, X509 *x509); /* check that they are exact match */ - /* Special Config Loading (backwards compatibility) */ -//bool loadCertificates(bool &oldFormat, std::map &keyValueMap); - static AuthSSL *getAuthSSL() throw() // pour obtenir l'instance { return instance_ssl; } @@ -192,61 +167,28 @@ bool CheckCertificate(std::string peerId, X509 *x509); /* check that they are e // the single instance of this static AuthSSL *instance_ssl; - /* Helper Functions */ -X509 * loadX509FromPEM(std::string pem); -X509 * loadX509FromFile(std::string fname, std::string hash); -bool saveX509ToFile(X509 *x509, std::string fname, std::string &hash); - -X509 * loadX509FromDER(const uint8_t *ptr, uint32_t len); -bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len); bool LocalStoreCert(X509* x509); +bool RemoveX509(std::string id); /*********** LOCKED Functions ******/ -//bool locked_FindCert(std::string id, sslcert **cert); - +bool locked_FindCert(std::string id, sslcert **cert); /* Data */ - RsMutex sslMtx; /**** LOCKING */ - - int init; - std::string mCertConfigFile; - std::string mNeighDir; - + /* these variables are constants -> don't need to protect */ SSL_CTX *sslctx; - std::string mOwnId; sslcert *mOwnCert; - EVP_PKEY *own_private_key; - EVP_PKEY *own_public_key; + + RsMutex sslMtx; /* protects all below */ + + + EVP_PKEY *mOwnPrivateKey; + EVP_PKEY *mOwnPublicKey; + + int init; std::map mCerts; }; -X509_REQ *GenerateX509Req( - std::string pkey_file, std::string passwd, - std::string name, std::string email, std::string org, - std::string loc, std::string state, std::string country, - int nbits_in, std::string &errString); - -X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days); - - -/* Helper Functions */ -int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::ostream &out); -std::string getX509NameString(X509_NAME *name); -std::string getX509CNString(X509_NAME *name); - -std::string getX509OrgString(X509_NAME *name); -std::string getX509LocString(X509_NAME *name); -std::string getX509CountryString(X509_NAME *name); - -std::string getX509Info(X509 *cert); -bool getX509id(X509 *x509, std::string &xid); - -int LoadCheckX509andGetIssuerName(const char *cert_file, - std::string &issuerName, std::string &userId); -int LoadCheckX509andGetLocation(const char *cert_file, - std::string &location, std::string &userId); - #endif // MRK_AUTH_SSL_HEADER diff --git a/libretroshare/src/pqi/p3notify.cc b/libretroshare/src/pqi/p3notify.cc index 8306f6715..1eac56d65 100644 --- a/libretroshare/src/pqi/p3notify.cc +++ b/libretroshare/src/pqi/p3notify.cc @@ -101,22 +101,28 @@ bool p3Notify::NotifyPopupMessage(uint32_t &ptype, std::string &name, std::strin /* Control over Messages */ bool p3Notify::GetSysMessageList(std::map &list) { + (void) list; /* suppress unused parameter warning */ return false; } bool p3Notify::GetPopupMessageList(std::map &list) { + (void) list; /* suppress unused parameter warning */ return false; } bool p3Notify::SetSysMessageMode(uint32_t sysid, uint32_t mode) { + (void) sysid; /* suppress unused parameter warning */ + (void) mode; /* suppress unused parameter warning */ return false; } bool p3Notify::SetPopupMessageMode(uint32_t ptype, uint32_t mode) { + (void) ptype; /* suppress unused parameter warning */ + (void) mode; /* suppress unused parameter warning */ return false; } diff --git a/libretroshare/src/pqi/pqi_base.h b/libretroshare/src/pqi/pqi_base.h index 53e3e6dfa..3b284c34b 100644 --- a/libretroshare/src/pqi/pqi_base.h +++ b/libretroshare/src/pqi/pqi_base.h @@ -125,7 +125,12 @@ virtual int status() { return 0; } virtual std::string PeerId() { return peerId; } // the callback from NetInterface Connection Events. -virtual int notifyEvent(NetInterface *ni, int event) { return 0; } +virtual int notifyEvent(NetInterface *ni, int event) + { + (void) ni; /* remove unused parameter warnings */ + (void) event; /* remove unused parameter warnings */ + return 0; + } private: diff --git a/libretroshare/src/pqi/pqibin.h b/libretroshare/src/pqi/pqibin.h index 8aba59692..3c0c44281 100644 --- a/libretroshare/src/pqi/pqibin.h +++ b/libretroshare/src/pqi/pqibin.h @@ -147,8 +147,17 @@ virtual int listen(); virtual int stoplistening(); virtual int disconnect(); virtual int reset(); -virtual bool connect_parameter(uint32_t type, uint32_t value) { return false; } -virtual int getConnectAddress(struct sockaddr_in &raddr) {return 0;} +virtual bool connect_parameter(uint32_t type, uint32_t value) + { + (void) type; /* suppress unused parameter warning */ + (void) value; /* suppress unused parameter warning */ + return false; + } +virtual int getConnectAddress(struct sockaddr_in &raddr) + { + (void) raddr; /* suppress unused parameter warning */ + return 0; + } // Bin Interface. virtual int tick(); diff --git a/libretroshare/src/pqi/pqilistener.h b/libretroshare/src/pqi/pqilistener.h index 5642ae2b1..0e0b980ee 100644 --- a/libretroshare/src/pqi/pqilistener.h +++ b/libretroshare/src/pqi/pqilistener.h @@ -38,7 +38,11 @@ virtual ~pqilistener() { return; } virtual int tick() { return 1; } virtual int status() { return 1; } -virtual int setListenAddr(struct sockaddr_in addr) { return 1; } +virtual int setListenAddr(struct sockaddr_in addr) + { + (void) addr; /* suppress unused parameter warning */ + return 1; + } virtual int setuplisten() { return 1; } virtual int resetlisten() { return 1; } diff --git a/libretroshare/src/pqi/pqipersongrp.h b/libretroshare/src/pqi/pqipersongrp.h index aba5e8266..61f19ce84 100644 --- a/libretroshare/src/pqi/pqipersongrp.h +++ b/libretroshare/src/pqi/pqipersongrp.h @@ -91,7 +91,12 @@ virtual pqiperson *createPerson(std::string id, pqilistener *listener) = 0; /* Overloaded RsItem Check * checks item->cid vs Person */ -virtual int checkOutgoingRsItem(RsItem *item, int global) { return 1; } +virtual int checkOutgoingRsItem(RsItem *item, int global) + { + (void) item; /* suppress unused parameter warning */ + (void) global; /* suppress unused parameter warning */ + return 1; + } private: diff --git a/libretroshare/src/pqi/pqissl.cc b/libretroshare/src/pqi/pqissl.cc index 2a04fca98..4a35fb7b4 100644 --- a/libretroshare/src/pqi/pqissl.cc +++ b/libretroshare/src/pqi/pqissl.cc @@ -29,6 +29,7 @@ #include "pqi/pqissl.h" #include "pqi/pqinetwork.h" +#include "pqi/sslfns.h" #include "util/rsnet.h" #include "util/rsdebug.h" diff --git a/libretroshare/src/pqi/pqissllistener.cc b/libretroshare/src/pqi/pqissllistener.cc index 9ad0c506e..2bf5df988 100644 --- a/libretroshare/src/pqi/pqissllistener.cc +++ b/libretroshare/src/pqi/pqissllistener.cc @@ -30,6 +30,7 @@ #include "pqi/pqissl.h" #include "pqi/pqissllistener.h" #include "pqi/pqinetwork.h" +#include "pqi/sslfns.h" #include #include diff --git a/libretroshare/src/pqi/sslfns.cc b/libretroshare/src/pqi/sslfns.cc new file mode 100644 index 000000000..9e182172c --- /dev/null +++ b/libretroshare/src/pqi/sslfns.cc @@ -0,0 +1,910 @@ +/* + * libretroshare/src/pqi: sslfns.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* Functions in this file are SSL only, + * and have no dependence on SSLRoot() etc. + * might need SSL_Init() to be called - thats it! + */ + +/******************** notify of new Cert **************************/ + +#include "pqi/sslfns.h" +#include "pqi/pqi_base.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +/**** + * #define AUTHSSL_DEBUG 1 + ***/ + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509_REQ *GenerateX509Req( + std::string pkey_file, std::string passwd, + std::string name, std::string email, std::string org, + std::string loc, std::string state, std::string country, + int nbits_in, std::string &errString) +{ + /* generate request */ + X509_REQ *req=X509_REQ_new(); + + // setup output. + BIO *bio_out = NULL; + bio_out = BIO_new(BIO_s_file()); + BIO_set_fp(bio_out,stdout,BIO_NOCLOSE); + + EVP_PKEY *pkey = NULL; + + // first generate a key.... + if ((pkey=EVP_PKEY_new()) == NULL) + { + fprintf(stderr,"GenerateX509Req: Couldn't Create Key\n"); + errString = "Couldn't Create Key"; + return 0; + } + + int nbits = 2048; + unsigned long e = 0x10001; + + if ((nbits_in >= 512) && (nbits_in <= 4096)) + { + nbits = nbits_in; + } + else + { + fprintf(stderr,"GenerateX509Req: strange num of nbits: %d\n", nbits_in); + fprintf(stderr,"GenerateX509Req: reverting to %d\n", nbits); + } + + + RSA *rsa = RSA_generate_key(nbits, e, NULL, NULL); + if ((rsa == NULL) || !EVP_PKEY_assign_RSA(pkey, rsa)) + { + if(rsa) RSA_free(rsa); + fprintf(stderr,"GenerateX509Req: Couldn't Generate RSA Key!\n"); + errString = "Couldn't generate RSA Key"; + return 0; + } + + + // open the file. + FILE *out; + if (NULL == (out = fopen(pkey_file.c_str(), "w"))) + { + fprintf(stderr,"GenerateX509Req: Couldn't Create Key File!"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Create Key File"; + return 0; + } + + const EVP_CIPHER *cipher = EVP_des_ede3_cbc(); + + if (!PEM_write_PrivateKey(out,pkey,cipher, + NULL,0,NULL,(void *) passwd.c_str())) + { + fprintf(stderr,"GenerateX509Req() Couldn't Save Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Save Private Key File"; + return 0; + } + fclose(out); + + // We have now created a private key.... + fprintf(stderr,"GenerateX509Req() Saved Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + /********** Test Loading the private Key.... ************/ + FILE *tst_in = NULL; + EVP_PKEY *tst_pkey = NULL; + if (NULL == (tst_in = fopen(pkey_file.c_str(), "rb"))) + { + fprintf(stderr,"GenerateX509Req() Couldn't Open Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Open Private Key"; + return 0; + } + + if (NULL == (tst_pkey = + PEM_read_PrivateKey(tst_in,NULL,NULL,(void *) passwd.c_str()))) + { + fprintf(stderr,"GenerateX509Req() Couldn't Read Private Key"); + fprintf(stderr," : %s\n", pkey_file.c_str()); + + errString = "Couldn't Read Private Key"; + return 0; + } + fclose(tst_in); + EVP_PKEY_free(tst_pkey); + /********** Test Loading the private Key.... ************/ + + /* Fill in details: fields. + req->req_info; + req->req_info->enc; + req->req_info->version; + req->req_info->subject; + req->req_info->pubkey; + ****************************/ + + long version = 0x00; + unsigned long chtype = MBSTRING_ASC; + X509_NAME *x509_name = X509_NAME_new(); + + // fill in the request. + + /**** X509_REQ -> Version ********************************/ + if (!X509_REQ_set_version(req,version)) /* version 1 */ + { + fprintf(stderr,"GenerateX509Req(): Couldn't Set Version!\n"); + + errString = "Couldn't Set Version"; + return 0; + } + /**** X509_REQ -> Version ********************************/ + /**** X509_REQ -> Key ********************************/ + + if (!X509_REQ_set_pubkey(req,pkey)) + { + fprintf(stderr,"GenerateX509Req() Couldn't Set PUBKEY !\n"); + + errString = "Couldn't Set PubKey"; + return 0; + } + + /**** SUBJECT ********************************/ + // create the name. + + // fields to add. + // commonName CN + // emailAddress (none) + // organizationName O + // localityName L + // stateOrProvinceName ST + // countryName C + + if (0 < strlen(name.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "CN", chtype, + (unsigned char *) name.c_str(), -1, -1, 0); + } + else + { + fprintf(stderr,"GenerateX509Req(): No Name -> Not creating X509 Cert Req\n"); + errString = "No Name, Aborting"; + return 0; + } + + if (0 < strlen(email.c_str())) + { + //X509_NAME_add_entry_by_txt(x509_name, "Email", 0, + // (unsigned char *) ui -> gen_email -> value(), -1, -1, 0); + X509_NAME_add_entry_by_NID(x509_name, 48, 0, + (unsigned char *) email.c_str(), -1, -1, 0); + } + + if (0 < strlen(org.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "O", chtype, + (unsigned char *) org.c_str(), -1, -1, 0); + } + + if (0 < strlen(loc.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "L", chtype, + (unsigned char *) loc.c_str(), -1, -1, 0); + } + + if (0 < strlen(state.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "ST", chtype, + (unsigned char *) state.c_str(), -1, -1, 0); + } + + if (0 < strlen(country.c_str())) + { + X509_NAME_add_entry_by_txt(x509_name, "C", chtype, + (unsigned char *) country.c_str(), -1, -1, 0); + } + + if (!X509_REQ_set_subject_name(req,x509_name)) + { + fprintf(stderr,"GenerateX509Req() Couldn't Set Name to Request!\n"); + X509_NAME_free(x509_name); + + errString = "Couldn't Set Name"; + return 0; + } + + X509_NAME_free(x509_name); + /**** SUBJECT ********************************/ + + if (!X509_REQ_sign(req,pkey,EVP_sha1())) + { + fprintf(stderr,"GenerateX509Req() Failed to Sign REQ\n"); + + errString = "Couldn't Sign Req"; + return 0; + } + + errString = "No Error"; + return req; +} + +#define SERIAL_RAND_BITS 64 + +X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days) +{ + const EVP_MD *digest = EVP_sha1(); + ASN1_INTEGER *serial = ASN1_INTEGER_new(); + EVP_PKEY *tmppkey; + X509 *x509 = X509_new(); + if (x509 == NULL) + return NULL; + + BIGNUM *btmp = BN_new(); + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," pseudo_rand\n"); + + return NULL; + } + if (!BN_to_ASN1_INTEGER(btmp, serial)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," int\n"); + + return NULL; + } + BN_free(btmp); + + if (!X509_set_serialNumber(x509, serial)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," serialNumber\n"); + + return NULL; + } + ASN1_INTEGER_free(serial); + + if (!X509_set_issuer_name(x509, issuer)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," issuer\n"); + + return NULL; + } + + if (!X509_gmtime_adj(x509->cert_info->validity->notBefore, 0)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," notBefore\n"); + + return NULL; + } + + //x509->cert_info->validity->notAfter + //if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days)) + if (!X509_gmtime_adj(x509->cert_info->validity->notAfter, (long)60*60*24*days)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," notAfter\n"); + + return NULL; + } + + if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req))) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," subject_name\n"); + + return NULL; + } + + + tmppkey = X509_REQ_get_pubkey(req); + if (!tmppkey || !X509_set_pubkey(x509,tmppkey)) + { + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," pubkey\n"); + + return NULL; + } + + + /* Cleanup Algorithm part */ + + X509_ALGOR *algor1 = x509->cert_info->signature; + X509_ALGOR *algor2 = x509->sig_alg; + + X509_ALGOR *a; + + a = algor1; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(digest->pkey_type); + + a = algor2; + ASN1_TYPE_free(a->parameter); + a->parameter=ASN1_TYPE_new(); + a->parameter->type=V_ASN1_NULL; + + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(digest->pkey_type); + + + if (!X509_sign(x509,privkey,digest)) + { + long e = ERR_get_error(); + + fprintf(stderr,"SignX509Certificate() Failed: "); + fprintf(stderr," signing Error: %ld\n", e); + + fprintf(stderr,"ERR: %s, %s, %s\n", + ERR_lib_error_string(e), + ERR_func_error_string(e), + ERR_reason_error_string(e)); + + int inl=i2d_X509(x509,NULL); + int outl=EVP_PKEY_size(privkey); + fprintf(stderr,"Size Check: inl: %d, outl: %d\n", inl, outl); + + return NULL; + } + + fprintf(stderr,"SignX509Certificate() Success\n"); + + return x509; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + + + /* Sign / Encrypt / Verify Data */ +bool SSL_SignDataBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey) +{ + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + unsigned int req_signlen = EVP_PKEY_size(pkey); + if (req_signlen > *signlen) + { + /* not enough space */ + std::cerr << "SignDataBin() Not Enough Sign SpacegnInit Failure!" << std::endl; + return false; + } + + 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, sign, signlen, pkey)) + { + std::cerr << "EVP_SignFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + return true; +} + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, X509 *cert) +{ + + /* cert->cert_info->key->pkey is NULL.... + * but is instantiated when we call X509_get_pubkey() + */ + + EVP_PKEY *peerkey = X509_get_pubkey(cert); + + /* must free this key afterwards */ + bool ret = SSL_VerifySignBin(data, len, sign, signlen, peerkey); + + EVP_PKEY_free(peerkey); + + return ret; +} + +/* Correct form of this function ... Internal for AuthSSL's usage + */ + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey) +{ + if(peerkey == NULL) + { + std::cerr << "VerifySignBin: no public key available !!" << std::endl ; + return false ; + } + + EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); + + if (0 == EVP_VerifyInit(mdctx, EVP_sha1())) + { + std::cerr << "EVP_VerifyInit Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if (0 == EVP_VerifyUpdate(mdctx, data, len)) + { + std::cerr << "EVP_VerifyUpdate Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + if(signlen == 0 || sign == NULL) + { + std::cerr << "AuthSSL::VerifySignBin: signlen=" << signlen << ", sign=" << (void*)sign << "!!" << std::endl ; + EVP_MD_CTX_destroy(mdctx); + return false ; + } + + if (0 == EVP_VerifyFinal(mdctx, sign, signlen, peerkey)) + { + std::cerr << "EVP_VerifyFinal Failure!" << std::endl; + + EVP_MD_CTX_destroy(mdctx); + return false; + } + + EVP_MD_CTX_destroy(mdctx); + return true; +} + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509 *loadX509FromPEM(std::string pem) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "loadX509FromPEM()"; + std::cerr << std::endl; +#endif + + /* Put the data into a mem BIO */ + char *certstr = strdup(pem.c_str()); + + BIO *bp = BIO_new_mem_buf(certstr, -1); + + X509 *pc = PEM_read_bio_X509(bp, NULL, NULL, NULL); + + BIO_free(bp); + free(certstr); + + return pc; +} + +std::string saveX509ToPEM(X509* x509) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "saveX509ToPEM() " << std::endl; +#endif + + /* get the cert first */ + std::string certstr; + BIO *bp = BIO_new(BIO_s_mem()); + + PEM_write_bio_X509(bp, x509); + + /* translate the bp data to a string */ + char *data; + int len = BIO_get_mem_data(bp, &data); + for(int i = 0; i < len; i++) + { + certstr += data[i]; + } + + BIO_free(bp); + + return certstr; +} + + +X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::LoadX509FromDER()"; + std::cerr << std::endl; +#endif + + X509 *tmp = NULL; +#ifdef __APPLE__ + unsigned char **certptr = (unsigned char **) &ptr; +#else + const unsigned char **certptr = (const unsigned char **) &ptr; +#endif + + X509 *x509 = d2i_X509(&tmp, certptr, len); + + return x509; +} + +bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len) +{ +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::saveX509ToDER()"; + std::cerr << std::endl; +#endif + + int certlen = i2d_X509(x509, (unsigned char **) ptr); + if (certlen > 0) + { + *len = certlen; + return true; + } + else + { + *len = 0; + return false; + } + return false; +} + + +bool getX509id(X509 *x509, std::string &xid) { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id()"; + std::cerr << std::endl; +#endif + + xid = ""; + if (x509 == NULL) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id() NULL pointer"; + std::cerr << std::endl; +#endif + return false; + } + + // get the signature from the cert, and copy to the array. + ASN1_BIT_STRING *signature = x509->signature; + int signlen = ASN1_STRING_length(signature); + if (signlen < CERTSIGNLEN) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "AuthSSL::getX509id() ERROR: Short Signature"; + std::cerr << std::endl; +#endif + return false; + } + + // else copy in the first CERTSIGNLEN. + unsigned char *signdata = ASN1_STRING_data(signature); + + std::ostringstream id; + /* switched to the other end of the signature. for + * more randomness + */ + for(int i = signlen - CERTSIGNLEN; i < signlen; i++) + { + id << std::hex << std::setw(2) << std::setfill('0') + << (uint16_t) (((uint8_t *) (signdata))[i]); + } + xid = id.str(); + return true; +} + + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +int pem_passwd_cb(char *buf, int size, int rwflag, void *password) +{ + /* remove unused parameter warnings */ + (void) rwflag; + + strncpy(buf, (char *)(password), size); + buf[size - 1] = '\0'; + return(strlen(buf)); +} + +/* XXX FIX */ +bool CheckX509Certificate(X509 *x509) +{ + + return true; +} + + +// Not dependent on sslroot. load, and detroys the X509 memory. +int LoadCheckX509(const char *cert_file, std::string &issuerName, std::string &location, std::string &userId) +{ + /* This function loads the X509 certificate from the file, + * and checks the certificate + */ + + FILE *tmpfp = fopen(cert_file, "r"); + if (tmpfp == NULL) + { +#ifdef AUTHSSL_DEBUG + std::cerr << "sslroot::LoadCheckAndGetX509Name()"; + std::cerr << " Failed to open Certificate File:" << cert_file; + std::cerr << std::endl; +#endif + return 0; + } + + // get xPGP certificate. + X509 *x509 = PEM_read_X509(tmpfp, NULL, NULL, NULL); + fclose(tmpfp); + + // check the certificate. + bool valid = false; + if (x509) + { + valid = CheckX509Certificate(x509); + if (valid) + { + valid = getX509id(x509, userId); + } + } + + if (valid) + { + // extract the name. + issuerName = getX509CNString(x509->cert_info->issuer); + location = getX509LocString(x509->cert_info->subject); + } + + #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; + } +} + + + + +std::string getX509NameString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + namestr += "\t"; + namestr += OBJ_nid2ln(OBJ_obj2nid(entry_obj)); + namestr += " : "; + + //namestr += entry_obj -> flags; + //namestr += entry_data -> length; + //namestr += entry_data -> type; + + //namestr += entry_data -> flags; + //entry -> set; + + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "NULL"; + } + + if (i + 1 < X509_NAME_entry_count(name)) + { + namestr += "\n"; + } + + } + return namestr; +} + + +std::string getX509CNString(X509_NAME *name) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp("CN", OBJ_nid2sn(OBJ_obj2nid(entry_obj)), 2)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509TypeString(X509_NAME *name, const char *type, int len) +{ + std::string namestr; + for(int i = 0; i < X509_NAME_entry_count(name); i++) + { + X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); + ASN1_STRING *entry_data = X509_NAME_ENTRY_get_data(entry); + ASN1_OBJECT *entry_obj = X509_NAME_ENTRY_get_object(entry); + + if (0 == strncmp(type, OBJ_nid2sn(OBJ_obj2nid(entry_obj)), len)) + { + if (entry_data -> data != NULL) + { + namestr += (char *) entry_data -> data; + } + else + { + namestr += "Unknown"; + } + return namestr; + } + } + return namestr; +} + + +std::string getX509LocString(X509_NAME *name) +{ + return getX509TypeString(name, "L", 2); +} + +std::string getX509OrgString(X509_NAME *name) +{ + return getX509TypeString(name, "O", 2); +} + + +std::string getX509CountryString(X509_NAME *name) +{ + return getX509TypeString(name, "C", 2); +} + + +std::string getX509Info(X509 *cert) +{ + std::stringstream out; + long l; + + out << "X509 Certificate:" << std::endl; + l=X509_get_version(cert); + out << " Version: " << l+1 << "(0x" << l << ")" << std::endl; + out << " Subject: " << std::endl; + out << " " << getX509NameString(cert->cert_info->subject); + out << std::endl; + out << std::endl; + out << " Signatures:" << std::endl; + return out.str(); +} + +/********** SSL ERROR STUFF ******************************************/ + +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, + std::ostream &out) +{ + (void) ssl; /* remove unused parameter warnings */ + + std::string reason; + + std::string mainreason = std::string("UNKNOWN ERROR CODE"); + if (err == SSL_ERROR_NONE) + { + mainreason = std::string("SSL_ERROR_NONE"); + } + else if (err == SSL_ERROR_ZERO_RETURN) + { + mainreason = std::string("SSL_ERROR_ZERO_RETURN"); + } + else if (err == SSL_ERROR_WANT_READ) + { + mainreason = std::string("SSL_ERROR_WANT_READ"); + } + else if (err == SSL_ERROR_WANT_WRITE) + { + mainreason = std::string("SSL_ERROR_WANT_WRITE"); + } + else if (err == SSL_ERROR_WANT_CONNECT) + { + mainreason = std::string("SSL_ERROR_WANT_CONNECT"); + } + else if (err == SSL_ERROR_WANT_ACCEPT) + { + mainreason = std::string("SSL_ERROR_WANT_ACCEPT"); + } + else if (err == SSL_ERROR_WANT_X509_LOOKUP) + { + mainreason = std::string("SSL_ERROR_WANT_X509_LOOKUP"); + } + else if (err == SSL_ERROR_SYSCALL) + { + mainreason = std::string("SSL_ERROR_SYSCALL"); + } + else if (err == SSL_ERROR_SSL) + { + mainreason = std::string("SSL_ERROR_SSL"); + } + out << "RetVal(" << retval; + out << ") -> SSL Error: " << mainreason << std::endl; + out << "\t + ERR Error: " << ERR_error_string(err2, NULL) << std::endl; + return 1; +} + diff --git a/libretroshare/src/pqi/sslfns.h b/libretroshare/src/pqi/sslfns.h new file mode 100644 index 000000000..4069c01a6 --- /dev/null +++ b/libretroshare/src/pqi/sslfns.h @@ -0,0 +1,115 @@ +#ifndef RS_PQI_SSL_HELPER_H +#define RS_PQI_SSL_HELPER_H + +/* + * libretroshare/src/pqi: sslfns.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/* Functions in this file are SSL only, + * and have no dependence on SSLRoot() etc. + * might need SSL_Init() to be called - thats it! + */ + +/******************** notify of new Cert **************************/ + +#include +#include + +#include +#include + +/**** + * #define AUTHSSL_DEBUG 1 + ***/ + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509_REQ *GenerateX509Req( + std::string pkey_file, std::string passwd, + std::string name, std::string email, std::string org, + std::string loc, std::string state, std::string country, + int nbits_in, std::string &errString); + +X509 *SignX509Certificate(X509_NAME *issuer, EVP_PKEY *privkey, X509_REQ *req, long days); + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + + + /* Sign / Encrypt / Verify Data */ +bool SSL_SignDataBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int *signlen, EVP_PKEY *pkey); + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, X509 *cert); + +bool SSL_VerifySignBin(const void *data, const uint32_t len, + unsigned char *sign, unsigned int signlen, EVP_PKEY *peerkey); + +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ +/********************************************************************************/ + +X509 *loadX509FromPEM(std::string pem); +std::string saveX509ToPEM(X509* x509); +X509 *loadX509FromDER(const uint8_t *ptr, uint32_t len); +bool saveX509ToDER(X509 *x509, uint8_t **ptr, uint32_t *len); + +bool getX509id(X509 *x509, std::string &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, std::string &issuerName, std::string &location, std::string &userId); + + +std::string getX509NameString(X509_NAME *name); +std::string getX509CNString(X509_NAME *name); +std::string getX509TypeString(X509_NAME *name, const char *type, int len); +std::string getX509LocString(X509_NAME *name); +std::string getX509OrgString(X509_NAME *name); +std::string getX509CountryString(X509_NAME *name); +std::string getX509Info(X509 *cert); + +/********** SSL ERROR STUFF ******************************************/ + +int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, + std::ostream &out); + +#endif /* RS_PQI_SSL_HELPER_H */ + diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index d7692d508..7afb147fc 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -44,6 +44,7 @@ #include #include "pqi/authssl.h" +#include "pqi/sslfns.h" #include "pqi/authgpg.h" class accountId @@ -795,16 +796,15 @@ static bool checkAccount(std::string accountdir, accountId &id) bool ret = false; /* check against authmanagers private keys */ - LoadCheckX509andGetLocation(cert_name.c_str(), id.location, id.sslId); - #ifdef AUTHSSL_DEBUG - std::cerr << "location: " << id.location << " id: " << id.sslId << std::endl; - #endif - - std::string tmpid; - if (LoadCheckX509andGetIssuerName(cert_name.c_str(), id.pgpId, tmpid)) + if (LoadCheckX509(cert_name.c_str(), id.pgpId, id.location, id.sslId)) { + #ifdef AUTHSSL_DEBUG + std::cerr << "location: " << id.location << " id: " << id.sslId << std::endl; + #endif + + #ifdef GPG_DEBUG - std::cerr << "issuerName: " << id.pgpId << " id: " << tmpid << std::endl; + std::cerr << "issuerName: " << id.pgpId << " id: " << id.sslId << std::endl; #endif RsInit::GetPGPLoginDetails(id.pgpId, id.pgpName, id.pgpEmail); #ifdef GPG_DEBUG @@ -936,7 +936,7 @@ bool RsInit::GenerateSSLCertificate(std::string gpg_id, std::string org, std nbits, errString); long days = 3000; - X509 *x509 = AuthSSL::getAuthSSL()->SignX509Req(req, days); + X509 *x509 = AuthSSL::getAuthSSL()->SignX509ReqWithGPG(req, days); X509_REQ_free(req); if (x509 == NULL) { @@ -1001,7 +1001,8 @@ bool RsInit::GenerateSSLCertificate(std::string gpg_id, std::string org, std /* try to load it, and get Id */ std::string location; - if (LoadCheckX509andGetLocation(cert_name.c_str(), location, sslId) == 0) { + std::string gpgid; + if (LoadCheckX509(cert_name.c_str(), gpgid, location, sslId) == 0) { std::cerr << "RsInit::GenerateSSLCertificate() Cannot check own signature, maybe the files are corrupted." << std::endl; return false; } @@ -1951,29 +1952,16 @@ int RsServer::StartupRetroShare() // Load up Certificates, and Old Configuration (if present) std::cerr << "Load up Certificates, and Old Configuration (if present)." << std::endl; - std::string certConfigFile = RsInitConfig::configDir.c_str(); - std::string certNeighDir = RsInitConfig::configDir.c_str(); std::string emergencySaveDir = RsInitConfig::configDir.c_str(); std::string emergencyPartialsDir = RsInitConfig::configDir.c_str(); - if (certConfigFile != "") + if (emergencySaveDir != "") { - certConfigFile += "/"; - certNeighDir += "/"; emergencySaveDir += "/"; emergencyPartialsDir += "/"; } - certConfigFile += configConfFile; - certNeighDir += configCertDir; emergencySaveDir += "Downloads"; emergencyPartialsDir += "Partials"; - /* if we've loaded an old format file! */ - std::map oldConfigMap; - - AuthSSL::getAuthSSL() -> setConfigDirectories(certConfigFile, certNeighDir); - - //AuthSSL::getAuthSSL() -> loadCertificates(); - /**************************************************************************/ /* setup classes / structures */ /**************************************************************************/ diff --git a/libretroshare/src/serialiser/rstlvkeys.cc b/libretroshare/src/serialiser/rstlvkeys.cc index 622911fe1..6660ea452 100644 --- a/libretroshare/src/serialiser/rstlvkeys.cc +++ b/libretroshare/src/serialiser/rstlvkeys.cc @@ -371,8 +371,6 @@ uint32_t RsTlvKeySignature::TlvSize() s += GetTlvStringSize(keyId); s += signData.TlvSize(); - s += GetTlvStringSize(sslCert); - return s; } @@ -395,7 +393,6 @@ bool RsTlvKeySignature::SetTlv(void *data, uint32_t size, uint32_t *offset) /* ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); ok &= signData.SetTlv(data, tlvend, offset); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_CERT_SSL, sslCert); return ok; @@ -428,11 +425,6 @@ bool RsTlvKeySignature::GetTlv(void *data, uint32_t size, uint32_t *offset) /* ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_KEYID, keyId); ok &= signData.GetTlv(data, tlvend, offset); - // The ssl cert is possibly void, i.e. an empty string. This is handled by - // GetTlvString(). - // - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_CERT_SSL, sslCert); - /*************************************************************************** * NB: extra components could be added (for future expansion of the type). * or be present (if this code is reading an extended version). diff --git a/libretroshare/src/serialiser/rstlvkeys.h b/libretroshare/src/serialiser/rstlvkeys.h index e918a0668..71ced334d 100644 --- a/libretroshare/src/serialiser/rstlvkeys.h +++ b/libretroshare/src/serialiser/rstlvkeys.h @@ -95,7 +95,7 @@ virtual std::ostream &print(std::ostream &out, uint16_t indent); std::string keyId; // Mandatory : RsTlvBinaryData signData; // Mandatory : - std::string sslCert; // Mandatory : + // NO Certificates in Signatures... add as separate data type. }; diff --git a/libretroshare/src/services/p3distrib.cc b/libretroshare/src/services/p3distrib.cc index 073c41635..1bdd42d68 100644 --- a/libretroshare/src/services/p3distrib.cc +++ b/libretroshare/src/services/p3distrib.cc @@ -2198,8 +2198,10 @@ std::string p3GroupDistrib::publishMsg(RsDistribMsg *msg, bool personalSign) if (AuthSSL::getAuthSSL()->SignDataBin(out_data, out_size, sigbuf, &siglen)) { signedMsg->personalSignature.signData.setBinData(sigbuf, siglen); - signedMsg->personalSignature.keyId = AuthSSL::getAuthSSL()->OwnId(); - signedMsg->personalSignature.sslCert = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); + signedMsg->personalSignature.keyId = AuthSSL::getAuthSSL()->OwnId(); + + // Don't want to send our certificate everywhere. + //signedMsg->personalSignature.sslCert = AuthSSL::getAuthSSL()->SaveOwnCertificateToString(); } } @@ -3009,30 +3011,13 @@ bool p3GroupDistrib::locked_validateDistribSignedMsg( /* now verify Personal signature */ if ((signOk == 1) && ((info.grpFlags & RS_DISTRIB_AUTHEN_MASK) & RS_DISTRIB_AUTHEN_REQ)) { - #ifdef DISTRIB_DEBUG - std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Personal Signature. sslCert : " << newMsg->personalSignature.sslCert << std::endl; - #endif - - //check the sslCert - RsPeerDetails pd; - if (!AuthSSL::getAuthSSL()->LoadDetailsFromStringCert(newMsg->personalSignature.sslCert, pd)) { - #ifdef DISTRIB_DEBUG - std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Fail - ssl cert not valid" << std::endl; - #endif - signOk = 0; - } else if (pd.id != newMsg->personalSignature.keyId) { - #ifdef DISTRIB_DEBUG - std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Fail - ssl cert id does not match the personal signature key id" << std::endl; - #endif - signOk = 0; - } else { unsigned int personalsiglen = newMsg->personalSignature.signData.bin_len; unsigned char *personalsigbuf = (unsigned char *) newMsg->personalSignature.signData.bin_data; - bool sslSign = AuthSSL::getAuthSSL()->VerifyOtherSignBin( + bool sslSign = AuthSSL::getAuthSSL()->VerifySignBin( newMsg->packet.bin_data, newMsg->packet.bin_len, - personalsigbuf, personalsiglen, newMsg->personalSignature.sslCert); + personalsigbuf, personalsiglen, newMsg->personalSignature.keyId); if (sslSign) { #ifdef DISTRIB_DEBUG std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Success for ssl signature." << std::endl; @@ -3044,7 +3029,6 @@ bool p3GroupDistrib::locked_validateDistribSignedMsg( #endif signOk = 0; } - } } if (signOk == 1)