2012-03-26 17:17:04 -04:00
# include <stdexcept>
# include <sstream>
# include <iostream>
# include <iomanip>
# include <stdlib.h>
2012-03-27 16:48:21 -04:00
# include <string.h>
2012-06-29 15:38:19 -04:00
# include <sys/stat.h>
2012-03-26 17:17:04 -04:00
2012-07-01 16:08:28 -04:00
# ifdef WINDOWS_SYS
2013-05-30 17:13:55 -04:00
# include <io.h>
2012-07-01 16:08:28 -04:00
# include "util/rsstring.h"
2012-10-09 19:07:51 -04:00
# include "util/rswin.h"
2012-07-01 16:08:28 -04:00
# endif
2012-03-26 17:17:04 -04:00
extern " C " {
# include <openpgpsdk/util.h>
2012-03-27 16:48:21 -04:00
# include <openpgpsdk/crypto.h>
2012-03-27 17:45:43 -04:00
# include <openpgpsdk/armour.h>
2012-03-27 16:48:21 -04:00
# include <openpgpsdk/keyring.h>
2012-03-27 17:45:43 -04:00
# include <openpgpsdk/readerwriter.h>
2012-04-01 17:10:54 -04:00
# include <openpgpsdk/validate.h>
2012-07-01 09:15:36 -04:00
# include <openpgpsdk/parse_local.h>
2012-03-26 17:17:04 -04:00
}
# include "pgphandler.h"
2012-04-29 07:57:03 -04:00
# include "retroshare/rsiface.h" // For rsicontrol.
2013-05-29 17:32:02 -04:00
# include "retroshare/rspeers.h" // For rsicontrol.
2012-06-29 15:38:19 -04:00
# include "util/rsdir.h"
2013-07-25 16:05:31 -04:00
# include "util/rsdiscspace.h"
2012-07-13 07:08:13 -04:00
# include "pgp/pgpkeyutil.h"
2012-06-29 15:38:19 -04:00
2013-07-06 15:59:42 -04:00
static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE = 64 ;
static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE = 64 ;
static const uint32_t PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE = 1024 ;
2012-07-09 16:20:36 -04:00
//#define DEBUG_PGPHANDLER 1
2012-08-07 15:16:17 -04:00
//#define PGPHANDLER_DSA_SUPPORT
2012-03-26 17:17:04 -04:00
2012-05-01 04:53:32 -04:00
PassphraseCallback PGPHandler : : _passphrase_callback = NULL ;
2012-04-01 08:52:15 -04:00
ops_keyring_t * PGPHandler : : allocateOPSKeyring ( )
{
ops_keyring_t * kr = ( ops_keyring_t * ) malloc ( sizeof ( ops_keyring_t ) ) ;
kr - > nkeys = 0 ;
kr - > nkeys_allocated = 0 ;
kr - > keys = 0 ;
return kr ;
}
2012-05-13 15:04:13 -04:00
ops_parse_cb_return_t cb_get_passphrase ( const ops_parser_content_t * content_ , ops_parse_cb_info_t * cbinfo ) // __attribute__((unused)))
{
const ops_parser_content_union_t * content = & content_ - > content ;
bool prev_was_bad = false ;
switch ( content_ - > tag )
{
case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD : prev_was_bad = true ;
case OPS_PARSER_CMD_GET_SK_PASSPHRASE :
{
std : : string passwd ;
2012-09-10 16:24:02 -04:00
std : : string uid_hint ;
if ( cbinfo - > cryptinfo . keydata - > nuids > 0 )
uid_hint = std : : string ( ( const char * ) cbinfo - > cryptinfo . keydata - > uids [ 0 ] . user_id ) ;
2012-05-13 15:04:13 -04:00
uid_hint + = " ( " + PGPIdType ( cbinfo - > cryptinfo . keydata - > key_id ) . toStdString ( ) + " ) " ;
passwd = PGPHandler : : passphraseCallback ( ) ( NULL , uid_hint . c_str ( ) , NULL , prev_was_bad ) ;
* ( content - > secret_key_passphrase . passphrase ) = ( char * ) ops_mallocz ( passwd . length ( ) + 1 ) ;
memcpy ( * ( content - > secret_key_passphrase . passphrase ) , passwd . c_str ( ) , passwd . length ( ) ) ;
return OPS_KEEP_MEMORY ;
}
break ;
default :
break ;
}
return OPS_RELEASE_MEMORY ;
}
2012-05-01 04:53:32 -04:00
void PGPHandler : : setPassphraseCallback ( PassphraseCallback cb )
{
_passphrase_callback = cb ;
}
2012-06-20 17:59:04 -04:00
PGPHandler : : PGPHandler ( const std : : string & pubring , const std : : string & secring , const std : : string & trustdb , const std : : string & pgp_lock_filename )
: pgphandlerMtx ( std : : string ( " PGPHandler " ) ) , _pubring_path ( pubring ) , _secring_path ( secring ) , _trustdb_path ( trustdb ) , _pgp_lock_filename ( pgp_lock_filename )
2012-03-26 17:17:04 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-06-12 16:31:13 -04:00
_pubring_changed = false ;
2012-06-20 17:59:04 -04:00
_trustdb_changed = false ;
2012-06-12 16:31:13 -04:00
RsStackFileLock flck ( _pgp_lock_filename ) ; // lock access to PGP directory.
2012-05-01 04:53:32 -04:00
if ( _passphrase_callback = = NULL )
std : : cerr < < " WARNING: before created a PGPHandler, you need to init the passphrase callback using PGPHandler::setPassphraseCallback() " < < std : : endl ;
2012-03-26 17:17:04 -04:00
// Allocate public and secret keyrings.
//
2012-04-01 08:52:15 -04:00
_pubring = allocateOPSKeyring ( ) ;
_secring = allocateOPSKeyring ( ) ;
2012-03-26 17:17:04 -04:00
2012-06-09 17:01:22 -04:00
// Check that the file exists. If not, create a void keyring.
FILE * ftest ;
2012-12-02 16:12:31 -05:00
ftest = RsDirUtil : : rs_fopen ( pubring . c_str ( ) , " rb " ) ;
2012-06-09 17:01:22 -04:00
bool pubring_exist = ( ftest ! = NULL ) ;
if ( ftest ! = NULL )
fclose ( ftest ) ;
2012-12-02 16:12:31 -05:00
ftest = RsDirUtil : : rs_fopen ( secring . c_str ( ) , " rb " ) ;
2012-06-09 17:01:22 -04:00
bool secring_exist = ( ftest ! = NULL ) ;
if ( ftest ! = NULL )
fclose ( ftest ) ;
2012-03-26 17:17:04 -04:00
// Read public and secret keyrings from supplied files.
//
2012-06-09 17:01:22 -04:00
if ( pubring_exist )
{
if ( ops_false = = ops_keyring_read_from_file ( _pubring , false , pubring . c_str ( ) ) )
throw std : : runtime_error ( " PGPHandler::readKeyRing(): cannot read pubring. File corrupted. " ) ;
}
else
std : : cerr < < " pubring file \" " < < pubring < < " \" not found. Creating a void keyring. " < < std : : endl ;
2012-03-26 17:17:04 -04:00
2012-04-01 08:52:15 -04:00
const ops_keydata_t * keydata ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _pubring , i ) ) ! = NULL )
{
2012-05-13 15:04:13 -04:00
PGPCertificateInfo & cert ( _public_keyring_map [ PGPIdType ( keydata - > key_id ) . toStdString ( ) ] ) ;
// Init all certificates.
initCertificateInfo ( cert , keydata , i ) ;
// Validate signatures.
validateAndUpdateSignatures ( cert , keydata ) ;
2012-04-01 08:52:15 -04:00
+ + i ;
}
2012-06-29 15:38:19 -04:00
_pubring_last_update_time = time ( NULL ) ;
2012-03-26 17:17:04 -04:00
std : : cerr < < " Pubring read successfully. " < < std : : endl ;
2012-06-09 17:01:22 -04:00
if ( secring_exist )
{
if ( ops_false = = ops_keyring_read_from_file ( _secring , false , secring . c_str ( ) ) )
throw std : : runtime_error ( " PGPHandler::readKeyRing(): cannot read secring. File corrupted. " ) ;
}
else
std : : cerr < < " secring file \" " < < secring < < " \" not found. Creating a void keyring. " < < std : : endl ;
2012-03-26 17:17:04 -04:00
2012-04-01 08:52:15 -04:00
i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _secring , i ) ) ! = NULL )
{
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _secret_keyring_map [ PGPIdType ( keydata - > key_id ) . toStdString ( ) ] , keydata , i ) ;
2012-04-01 08:52:15 -04:00
+ + i ;
}
2012-06-29 15:38:19 -04:00
_secring_last_update_time = time ( NULL ) ;
2012-04-01 08:52:15 -04:00
2012-03-26 17:17:04 -04:00
std : : cerr < < " Secring read successfully. " < < std : : endl ;
2012-06-20 17:59:04 -04:00
locked_readPrivateTrustDatabase ( ) ;
2012-07-08 17:06:41 -04:00
_trustdb_last_update_time = time ( NULL ) ;
2012-03-26 17:17:04 -04:00
}
2012-04-09 13:03:47 -04:00
void PGPHandler : : initCertificateInfo ( PGPCertificateInfo & cert , const ops_keydata_t * keydata , uint32_t index )
{
// Parse certificate name
//
2012-04-22 07:36:34 -04:00
if ( keydata - > uids ! = NULL )
{
std : : string namestring ( ( char * ) keydata - > uids [ 0 ] . user_id ) ;
cert . _name = " " ;
2012-04-29 07:57:03 -04:00
uint32_t i = 0 ;
2012-04-22 07:36:34 -04:00
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ( ' & & namestring [ i ] ! = ' < ' ) { cert . _name + = namestring [ i ] ; + + i ; }
2012-04-09 13:03:47 -04:00
2012-08-02 14:23:20 -04:00
// trim right spaces
std : : string : : size_type found = cert . _name . find_last_not_of ( ' ' ) ;
if ( found ! = std : : string : : npos )
cert . _name . erase ( found + 1 ) ;
else
cert . _name . clear ( ) ; // all whitespace
2012-04-22 07:36:34 -04:00
std : : string & next = ( namestring [ i ] = = ' ( ' ) ? cert . _comment : cert . _email ;
+ + i ;
next = " " ;
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ) ' & & namestring [ i ] ! = ' > ' ) { next + = namestring [ i ] ; + + i ; }
2012-04-09 13:03:47 -04:00
2012-04-22 07:36:34 -04:00
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ( ' & & namestring [ i ] ! = ' < ' ) { next + = namestring [ i ] ; + + i ; }
2012-04-26 15:37:15 -04:00
if ( i < namestring . length ( ) )
{
std : : string & next2 = ( namestring [ i ] = = ' ( ' ) ? cert . _comment : cert . _email ;
+ + i ;
next2 = " " ;
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ) ' & & namestring [ i ] ! = ' > ' ) { next2 + = namestring [ i ] ; + + i ; }
}
2012-04-22 07:36:34 -04:00
}
2012-04-09 13:03:47 -04:00
cert . _trustLvl = 1 ; // to be setup accordingly
2012-05-01 04:53:32 -04:00
cert . _validLvl = 1 ; // to be setup accordingly
2012-04-09 13:03:47 -04:00
cert . _key_index = index ;
2012-04-26 15:37:15 -04:00
cert . _flags = 0 ;
2013-05-31 03:30:05 -04:00
cert . _time_stamp = 0 ; // "never" by default. Will be updated by trust database, and effective key usage.
2012-04-09 13:03:47 -04:00
2012-08-02 08:14:50 -04:00
switch ( keydata - > key . pkey . algorithm )
{
case OPS_PKA_RSA : cert . _type = PGPCertificateInfo : : PGP_CERTIFICATE_TYPE_RSA ;
break ;
case OPS_PKA_DSA : cert . _type = PGPCertificateInfo : : PGP_CERTIFICATE_TYPE_DSA ;
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ;
break ;
default : cert . _type = PGPCertificateInfo : : PGP_CERTIFICATE_TYPE_UNKNOWN ;
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ;
break ;
}
2012-04-22 07:36:34 -04:00
ops_fingerprint_t f ;
ops_fingerprint ( & f , & keydata - > key . pkey ) ;
cert . _fpr = PGPFingerprintType ( f . fingerprint ) ;
2012-05-13 15:04:13 -04:00
}
2012-07-02 16:46:14 -04:00
bool PGPHandler : : validateAndUpdateSignatures ( PGPCertificateInfo & cert , const ops_keydata_t * keydata )
2012-05-13 15:04:13 -04:00
{
ops_validate_result_t * result = ( ops_validate_result_t * ) ops_mallocz ( sizeof * result ) ;
ops_boolean_t res = ops_validate_key_signatures ( result , keydata , _pubring , cb_get_passphrase ) ;
2012-05-01 14:45:24 -04:00
2012-06-29 15:38:19 -04:00
if ( res = = ops_false )
2012-09-17 16:19:02 -04:00
{
static ops_boolean_t already = 0 ;
if ( ! already )
{
std : : cerr < < " (WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures. " < < std : : endl ;
already = 1 ;
}
}
2012-06-29 15:38:19 -04:00
2012-07-02 16:46:14 -04:00
bool ret = false ;
2012-05-01 14:45:24 -04:00
// Parse signers.
//
2012-05-13 15:04:13 -04:00
if ( result ! = NULL )
for ( size_t i = 0 ; i < result - > valid_count ; + + i )
2012-07-02 16:46:14 -04:00
{
std : : string signer_str = PGPIdType ( result - > valid_sigs [ i ] . signer_id ) . toStdString ( ) ;
if ( cert . signers . find ( signer_str ) = = cert . signers . end ( ) )
{
cert . signers . insert ( signer_str ) ;
ret = true ;
}
}
2012-05-13 15:04:13 -04:00
ops_validate_result_free ( result ) ;
2012-07-02 16:46:14 -04:00
return ret ;
2012-04-09 13:03:47 -04:00
}
2012-03-26 17:17:04 -04:00
PGPHandler : : ~ PGPHandler ( )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-03-26 17:17:04 -04:00
std : : cerr < < " Freeing PGPHandler. Deleting keyrings. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-03-26 17:17:04 -04:00
2012-04-01 08:52:15 -04:00
// no need to free the the _map_ elements. They will be freed by the following calls:
//
2012-03-26 17:17:04 -04:00
ops_keyring_free ( _pubring ) ;
ops_keyring_free ( _secring ) ;
free ( _pubring ) ;
free ( _secring ) ;
}
2012-03-27 16:48:21 -04:00
2012-04-09 13:03:47 -04:00
bool PGPHandler : : printKeys ( ) const
{
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-04-22 07:36:34 -04:00
std : : cerr < < " Printing details of all " < < std : : dec < < _public_keyring_map . size ( ) < < " keys: " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-04-22 07:36:34 -04:00
2012-04-09 13:03:47 -04:00
for ( std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . begin ( ) ) ; it ! = _public_keyring_map . end ( ) ; it + + )
{
std : : cerr < < " PGP Key: " < < it - > first < < std : : endl ;
std : : cerr < < " \t Name : " < < it - > second . _name < < std : : endl ;
std : : cerr < < " \t Email : " < < it - > second . _email < < std : : endl ;
std : : cerr < < " \t OwnSign : " < < ( it - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ) < < std : : endl ;
2012-06-14 16:13:31 -04:00
std : : cerr < < " \t Accept Connect: " < < ( it - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ) < < std : : endl ;
2012-04-09 13:03:47 -04:00
std : : cerr < < " \t trustLvl : " < < it - > second . _trustLvl < < std : : endl ;
std : : cerr < < " \t validLvl : " < < it - > second . _validLvl < < std : : endl ;
2013-05-21 18:38:00 -04:00
std : : cerr < < " \t Use time stamp: " < < it - > second . _time_stamp < < std : : endl ;
2012-04-22 07:36:34 -04:00
std : : cerr < < " \t fingerprint : " < < it - > second . _fpr . toStdString ( ) < < std : : endl ;
2012-05-01 14:45:24 -04:00
std : : cerr < < " \t Signers : " < < it - > second . signers . size ( ) < < std : : endl ;
2012-04-09 13:03:47 -04:00
std : : set < std : : string > : : const_iterator sit ;
for ( sit = it - > second . signers . begin ( ) ; sit ! = it - > second . signers . end ( ) ; sit + + )
{
std : : cerr < < " \t \t Signer ID: " < < * sit < < " , Name: " ;
2012-06-06 16:31:19 -04:00
const PGPCertificateInfo * info = PGPHandler : : getCertificateInfo ( PGPIdType ( * sit ) ) ;
2012-04-09 13:03:47 -04:00
if ( info ! = NULL )
std : : cerr < < info - > _name ;
std : : cerr < < std : : endl ;
}
}
2012-05-01 14:45:24 -04:00
std : : cerr < < " Public keyring list from OPS: " < < std : : endl ;
ops_keyring_list ( _pubring ) ;
2012-04-09 13:03:47 -04:00
return true ;
}
2012-07-08 17:06:41 -04:00
bool PGPHandler : : haveSecretKey ( const PGPIdType & id ) const
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
return locked_getSecretKey ( id ) ! = NULL ;
2012-07-08 17:06:41 -04:00
}
2012-04-09 13:03:47 -04:00
const PGPCertificateInfo * PGPHandler : : getCertificateInfo ( const PGPIdType & id ) const
2012-03-27 16:48:21 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . find ( id . toStdString ( ) ) ) ;
2012-03-27 16:48:21 -04:00
2012-04-09 13:03:47 -04:00
if ( it ! = _public_keyring_map . end ( ) )
return & it - > second ;
else
return NULL ;
2012-03-27 16:48:21 -04:00
}
bool PGPHandler : : availableGPGCertificatesWithPrivateKeys ( std : : list < PGPIdType > & ids )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-03-27 16:48:21 -04:00
// go through secret keyring, and check that we have the pubkey as well.
//
const ops_keydata_t * keydata = NULL ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _secring , i + + ) ) ! = NULL )
2012-06-29 15:38:19 -04:00
if ( ops_keyring_find_key_by_id ( _pubring , keydata - > key_id ) ! = NULL ) // check that the key is in the pubring as well
{
2012-08-07 15:16:17 -04:00
# ifdef PGPHANDLER_DSA_SUPPORT
if ( keydata - > key . pkey . algorithm = = OPS_PKA_RSA | | keydata - > key . pkey . algorithm = = OPS_PKA_DSA )
# else
2012-06-14 16:13:31 -04:00
if ( keydata - > key . pkey . algorithm = = OPS_PKA_RSA )
2012-08-07 15:16:17 -04:00
# endif
2012-06-14 16:13:31 -04:00
ids . push_back ( PGPIdType ( keydata - > key_id ) ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-14 16:13:31 -04:00
else
std : : cerr < < " Skipping keypair " < < PGPIdType ( keydata - > key_id ) . toStdString ( ) < < " , unsupported algorithm: " < < keydata - > key . pkey . algorithm < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
}
2012-03-27 16:48:21 -04:00
return true ;
}
2012-07-01 10:34:11 -04:00
bool PGPHandler : : GeneratePGPCertificate ( const std : : string & name , const std : : string & email , const std : : string & passphrase , PGPIdType & pgpId , std : : string & errString )
2012-03-27 16:48:21 -04:00
{
2013-07-06 15:59:42 -04:00
// Some basic checks
2013-07-25 16:05:31 -04:00
if ( ! RsDiscSpace : : checkForDiscSpace ( RS_PGP_DIRECTORY ) )
{
errString = std : : string ( " (EE) low disc space in pgp directory. Can't write safely to keyring. " ) ;
return false ;
}
2013-07-06 15:59:42 -04:00
if ( name . length ( ) > PGP_CERTIFICATE_LIMIT_MAX_NAME_SIZE )
{
errString = std : : string ( " (EE) name in certificate exceeds the maximum allowed name size " ) ;
return false ;
}
if ( email . length ( ) > PGP_CERTIFICATE_LIMIT_MAX_EMAIL_SIZE )
{
2013-07-06 17:25:07 -04:00
errString = std : : string ( " (EE) email in certificate exceeds the maximum allowed email size " ) ;
2013-07-06 15:59:42 -04:00
return false ;
}
2013-07-06 17:25:07 -04:00
if ( passphrase . length ( ) > PGP_CERTIFICATE_LIMIT_MAX_PASSWD_SIZE )
2013-07-06 15:59:42 -04:00
{
2013-07-06 17:25:07 -04:00
errString = std : : string ( " (EE) passphrase in certificate exceeds the maximum allowed passphrase size " ) ;
2013-07-06 15:59:42 -04:00
return false ;
}
// Now the real thing
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-07-01 18:24:37 -04:00
RsStackFileLock flck ( _pgp_lock_filename ) ; // lock access to PGP directory.
2012-03-27 16:48:21 -04:00
static const int KEY_NUMBITS = 2048 ;
2012-07-01 10:34:11 -04:00
// 1 - generate keypair - RSA-2048
//
2012-03-27 16:48:21 -04:00
ops_user_id_t uid ;
2012-07-08 17:06:41 -04:00
char * s = strdup ( ( name + " (Generated by RetroShare) < " + email + " > " ) . c_str ( ) ) ;
2012-03-27 16:48:21 -04:00
uid . user_id = ( unsigned char * ) s ;
2012-07-01 17:40:44 -04:00
unsigned long int e = 65537 ; // some prime number
2012-03-27 16:48:21 -04:00
ops_keydata_t * key = ops_rsa_create_selfsigned_keypair ( KEY_NUMBITS , e , & uid ) ;
2012-04-01 12:43:23 -04:00
free ( s ) ;
2012-03-27 16:48:21 -04:00
if ( ! key )
return false ;
2012-07-01 17:40:44 -04:00
// 2 - save the private key encrypted to a temporary memory buffer, so as to read an encrypted key to memory
2012-04-01 08:52:15 -04:00
ops_create_info_t * cinfo = NULL ;
ops_memory_t * buf = NULL ;
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
2012-07-01 17:40:44 -04:00
if ( ! ops_write_transferable_secret_key ( key , ( unsigned char * ) passphrase . c_str ( ) , passphrase . length ( ) , ops_false , cinfo ) )
{
2012-07-11 12:17:49 -04:00
errString = std : : string ( " (EE) Cannot encode secret key to memory!! " ) ;
2012-07-01 17:40:44 -04:00
return false ;
}
2012-04-01 08:52:15 -04:00
2012-07-01 17:40:44 -04:00
// 3 - read the memory chunk into an encrypted keyring
2012-04-01 08:52:15 -04:00
2012-07-01 10:34:11 -04:00
ops_keyring_t * tmp_secring = allocateOPSKeyring ( ) ;
2012-07-01 17:40:44 -04:00
2012-07-01 10:34:11 -04:00
if ( ! ops_keyring_read_from_mem ( tmp_secring , ops_false , buf ) )
2012-04-01 08:52:15 -04:00
{
2012-07-11 12:17:49 -04:00
errString = std : : string ( " (EE) Cannot re-read key from memory!! " ) ;
2012-04-01 08:52:15 -04:00
return false ;
}
ops_teardown_memory_write ( cinfo , buf ) ; // cleanup memory
2012-07-01 17:40:44 -04:00
// 4 - copy the encrypted private key to the private keyring
2012-04-01 08:52:15 -04:00
2012-07-01 10:34:11 -04:00
pgpId = PGPIdType ( tmp_secring - > keys [ 0 ] . key_id ) ;
addNewKeyToOPSKeyring ( _secring , tmp_secring - > keys [ 0 ] ) ;
initCertificateInfo ( _secret_keyring_map [ pgpId . toStdString ( ) ] , & tmp_secring - > keys [ 0 ] , _secring - > nkeys - 1 ) ;
2012-04-01 08:52:15 -04:00
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-04-01 08:52:15 -04:00
std : : cerr < < " Added new secret key with id " < < pgpId . toStdString ( ) < < " to secret keyring. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-07-01 10:34:11 -04:00
ops_keyring_free ( tmp_secring ) ;
free ( tmp_secring ) ;
2012-04-01 08:52:15 -04:00
2012-07-01 17:50:48 -04:00
// 5 - add key to secret keyring on disk.
2012-04-01 17:10:54 -04:00
2012-07-01 18:24:37 -04:00
cinfo = NULL ;
2013-07-25 16:05:31 -04:00
std : : string secring_path_tmp = _secring_path + " .tmp " ;
if ( RsDirUtil : : fileExists ( _secring_path ) & & ! RsDirUtil : : copyFile ( _secring_path , secring_path_tmp ) )
{
errString = std : : string ( " Cannot copy secret keyring !! Disk full? Out of disk quota? " ) ;
return false ;
}
int fd = ops_setup_file_append ( & cinfo , secring_path_tmp . c_str ( ) ) ;
2012-07-01 17:50:48 -04:00
2012-07-01 18:24:37 -04:00
if ( ! ops_write_transferable_secret_key ( key , ( unsigned char * ) passphrase . c_str ( ) , passphrase . length ( ) , ops_false , cinfo ) )
{
2012-07-11 12:17:49 -04:00
errString = std : : string ( " Cannot encode secret key to disk!! Disk full? Out of disk quota? " ) ;
2012-07-01 18:24:37 -04:00
return false ;
2012-07-01 17:40:44 -04:00
}
2012-07-01 18:24:37 -04:00
ops_teardown_file_write ( cinfo , fd ) ;
2012-07-01 17:40:44 -04:00
2013-07-25 16:05:31 -04:00
if ( ! RsDirUtil : : renameFile ( secring_path_tmp , _secring_path ) )
{
errString = std : : string ( " Cannot rename tmp secret key file " ) + secring_path_tmp + " into " + _secring_path + " . Disk error? " ;
return false ;
}
2012-07-02 16:46:14 -04:00
// 6 - copy the public key to the public keyring on disk
2012-07-01 17:40:44 -04:00
2012-07-02 16:46:14 -04:00
cinfo = NULL ;
2013-07-25 16:05:31 -04:00
std : : string pubring_path_tmp = _pubring_path + " .tmp " ;
if ( RsDirUtil : : fileExists ( _pubring_path ) & & ! RsDirUtil : : copyFile ( _pubring_path , pubring_path_tmp ) )
{
errString = std : : string ( " Cannot encode secret key to disk!! Disk full? Out of disk quota? " ) ;
return false ;
}
fd = ops_setup_file_append ( & cinfo , pubring_path_tmp . c_str ( ) ) ;
2012-07-01 17:40:44 -04:00
if ( ! ops_write_transferable_public_key ( key , ops_false , cinfo ) )
{
2012-07-11 12:17:49 -04:00
errString = std : : string ( " Cannot encode secret key to memory!! " ) ;
2012-07-01 17:40:44 -04:00
return false ;
}
2012-07-02 16:46:14 -04:00
ops_teardown_file_write ( cinfo , fd ) ;
2012-07-01 10:34:11 -04:00
2013-07-25 16:05:31 -04:00
if ( ! RsDirUtil : : renameFile ( pubring_path_tmp , _pubring_path ) )
{
errString = std : : string ( " Cannot rename tmp public key file " ) + pubring_path_tmp + " into " + _pubring_path + " . Disk error? " ;
return false ;
}
2012-07-02 16:46:14 -04:00
// 7 - clean
ops_keydata_free ( key ) ;
2012-07-01 10:34:11 -04:00
2012-07-02 16:46:14 -04:00
// 8 - re-read the key from the public keyring, and add it to memory.
_pubring_last_update_time = 0 ; // force update pubring from disk.
locked_syncPublicKeyring ( ) ;
2012-04-01 17:10:54 -04:00
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-04-01 17:10:54 -04:00
std : : cerr < < " Added new public key with id " < < pgpId . toStdString ( ) < < " to public keyring. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-04-01 17:10:54 -04:00
2012-07-02 16:46:14 -04:00
// 9 - Update some flags.
2012-05-13 15:04:13 -04:00
2012-07-01 17:50:48 -04:00
privateTrustCertificate ( pgpId , PGPCertificateInfo : : PGP_CERTIFICATE_TRUST_ULTIMATE ) ;
2012-06-12 16:31:13 -04:00
2012-03-29 17:51:37 -04:00
return true ;
}
2012-08-13 15:37:50 -04:00
std : : string PGPHandler : : makeRadixEncodedPGPKey ( const ops_keydata_t * key , bool include_signatures )
2012-03-29 17:51:37 -04:00
{
2012-03-27 17:45:43 -04:00
ops_create_info_t * cinfo ;
2012-04-01 08:52:15 -04:00
ops_memory_t * buf = NULL ;
2012-03-27 17:45:43 -04:00
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
2012-08-13 15:37:50 -04:00
ops_boolean_t armoured = ops_true ;
2012-03-27 17:45:43 -04:00
2012-07-10 17:40:53 -04:00
if ( key - > type = = OPS_PTAG_CT_PUBLIC_KEY )
{
if ( ops_write_transferable_public_key_from_packet_data ( key , armoured , cinfo ) ! = ops_true )
return " ERROR: This key cannot be processed by RetroShare because \n DSA certificates are not yet handled. " ;
}
else if ( key - > type = = OPS_PTAG_CT_ENCRYPTED_SECRET_KEY )
{
if ( ops_write_transferable_secret_key_from_packet_data ( key , armoured , cinfo ) ! = ops_true )
return " ERROR: This key cannot be processed by RetroShare because \n DSA certificates are not yet handled. " ;
}
else
{
std : : cerr < < " Unhandled key type " < < key - > type < < std : : endl ;
return " ERROR: Cannot write key. Unhandled key type. " ;
}
2012-06-13 16:54:39 -04:00
2012-03-29 17:51:37 -04:00
ops_writer_close ( cinfo ) ;
2012-03-27 17:45:43 -04:00
2012-08-13 15:37:50 -04:00
std : : string res ( ( char * ) ops_memory_get_data ( buf ) , ops_memory_get_length ( buf ) ) ;
2012-03-29 17:51:37 -04:00
ops_teardown_memory_write ( cinfo , buf ) ;
2012-03-27 17:45:43 -04:00
2012-08-13 15:37:50 -04:00
if ( ! include_signatures )
{
std : : string tmp ;
if ( PGPKeyManagement : : createMinimalKey ( res , tmp ) )
res = tmp ;
}
return res ;
2012-03-29 17:51:37 -04:00
}
2013-05-21 18:38:00 -04:00
const ops_keydata_t * PGPHandler : : locked_getSecretKey ( const PGPIdType & id ) const
2012-04-01 08:52:15 -04:00
{
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _secret_keyring_map . find ( id . toStdString ( ) ) ;
2012-04-01 08:52:15 -04:00
if ( res = = _secret_keyring_map . end ( ) )
return NULL ;
else
2012-04-09 13:03:47 -04:00
return ops_keyring_get_key_by_index ( _secring , res - > second . _key_index ) ;
2012-04-01 08:52:15 -04:00
}
2013-05-21 18:38:00 -04:00
const ops_keydata_t * PGPHandler : : locked_getPublicKey ( const PGPIdType & id , bool stamp_the_key ) const
2012-04-01 08:52:15 -04:00
{
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id . toStdString ( ) ) ;
2012-04-01 08:52:15 -04:00
if ( res = = _public_keyring_map . end ( ) )
return NULL ;
else
2013-05-21 18:38:00 -04:00
{
if ( stamp_the_key ) // Should we stamp the key as used?
{
static time_t last_update_db_because_of_stamp = 0 ;
time_t now = time ( NULL ) ;
res - > second . _time_stamp = now ;
if ( now > last_update_db_because_of_stamp + 3600 ) // only update database once every hour. No need to do it more often.
{
_trustdb_changed = true ;
last_update_db_because_of_stamp = now ;
}
}
2012-04-09 13:03:47 -04:00
return ops_keyring_get_key_by_index ( _pubring , res - > second . _key_index ) ;
2013-05-21 18:38:00 -04:00
}
2012-04-01 08:52:15 -04:00
}
2012-08-13 15:37:50 -04:00
std : : string PGPHandler : : SaveCertificateToString ( const PGPIdType & id , bool include_signatures ) const
2012-03-29 17:51:37 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * key = locked_getPublicKey ( id , false ) ;
2012-03-29 17:51:37 -04:00
if ( key = = NULL )
{
std : : cerr < < " Cannot output key " < < id . toStdString ( ) < < " : not found in keyring. " < < std : : endl ;
return " " ;
}
2012-08-13 15:37:50 -04:00
return makeRadixEncodedPGPKey ( key , include_signatures ) ;
}
bool PGPHandler : : exportPublicKey ( const PGPIdType & id , unsigned char * & mem_block , size_t & mem_size , bool armoured , bool include_signatures ) const
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * key = locked_getPublicKey ( id , false ) ;
2012-08-13 15:37:50 -04:00
mem_block = NULL ;
if ( key = = NULL )
{
std : : cerr < < " Cannot output key " < < id . toStdString ( ) < < " : not found in keyring. " < < std : : endl ;
return false ;
}
ops_create_info_t * cinfo ;
ops_memory_t * buf = NULL ;
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
if ( ops_write_transferable_public_key_from_packet_data ( key , armoured , cinfo ) ! = ops_true )
{
std : : cerr < < " ERROR: This key cannot be processed by RetroShare because \n DSA certificates are not yet handled. " < < std : : endl ;
return false ;
}
ops_writer_close ( cinfo ) ;
mem_block = new unsigned char [ ops_memory_get_length ( buf ) ] ;
mem_size = ops_memory_get_length ( buf ) ;
memcpy ( mem_block , ops_memory_get_data ( buf ) , mem_size ) ;
ops_teardown_memory_write ( cinfo , buf ) ;
if ( ! include_signatures )
{
size_t new_size ;
PGPKeyManagement : : findLengthOfMinimalKey ( mem_block , mem_size , new_size ) ;
mem_size = new_size ;
}
return true ;
2012-03-27 16:48:21 -04:00
}
2012-07-10 17:40:53 -04:00
bool PGPHandler : : exportGPGKeyPair ( const std : : string & filename , const PGPIdType & exported_key_id ) const
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * pubkey = locked_getPublicKey ( exported_key_id , false ) ;
2012-07-10 17:40:53 -04:00
if ( pubkey = = NULL )
{
std : : cerr < < " Cannot output key " < < exported_key_id . toStdString ( ) < < " : not found in public keyring. " < < std : : endl ;
return false ;
}
2013-05-21 18:38:00 -04:00
const ops_keydata_t * seckey = locked_getSecretKey ( exported_key_id ) ;
2012-07-10 17:40:53 -04:00
if ( seckey = = NULL )
{
std : : cerr < < " Cannot output key " < < exported_key_id . toStdString ( ) < < " : not found in secret keyring. " < < std : : endl ;
return false ;
}
2012-12-02 16:12:31 -05:00
FILE * f = RsDirUtil : : rs_fopen ( filename . c_str ( ) , " w " ) ;
2012-07-10 17:40:53 -04:00
if ( f = = NULL )
{
std : : cerr < < " Cannot output key " < < exported_key_id . toStdString ( ) < < " : file " < < filename < < " cannot be written. Please check for permissions, quotas, disk space. " < < std : : endl ;
return false ;
}
2012-08-13 15:37:50 -04:00
fprintf ( f , " %s \n " , makeRadixEncodedPGPKey ( pubkey , true ) . c_str ( ) ) ;
fprintf ( f , " %s \n " , makeRadixEncodedPGPKey ( seckey , true ) . c_str ( ) ) ;
2012-07-10 17:40:53 -04:00
fclose ( f ) ;
return true ;
}
2012-08-13 15:37:50 -04:00
bool PGPHandler : : getGPGDetailsFromBinaryBlock ( const unsigned char * mem_block , size_t mem_size , std : : string & key_id , std : : string & name , std : : list < std : : string > & signers ) const
{
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
ops_memory_t * mem = ops_memory_new ( ) ;
ops_memory_add ( mem , mem_block , mem_size ) ;
if ( ! ops_keyring_read_from_mem ( tmp_keyring , ops_false , mem ) )
{
ops_keyring_free ( tmp_keyring ) ;
free ( tmp_keyring ) ;
ops_memory_release ( mem ) ;
free ( mem ) ;
std : : cerr < < " Could not read key. Format error? " < < std : : endl ;
//error_string = std::string("Could not read key. Format error?") ;
return false ;
}
ops_memory_release ( mem ) ;
free ( mem ) ;
//error_string.clear() ;
2012-08-14 15:49:50 -04:00
if ( tmp_keyring - > nkeys ! = 1 )
{
std : : cerr < < " No or incomplete/invalid key in supplied pgp block. " < < std : : endl ;
return false ;
}
2012-08-13 15:37:50 -04:00
key_id = PGPIdType ( tmp_keyring - > keys [ 0 ] . key_id ) . toStdString ( ) ;
name = std : : string ( ( char * ) tmp_keyring - > keys [ 0 ] . uids [ 0 ] . user_id ) ;
// now parse signatures.
//
ops_validate_result_t * result = ( ops_validate_result_t * ) ops_mallocz ( sizeof * result ) ;
ops_boolean_t res ;
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
res = ops_validate_key_signatures ( result , & tmp_keyring - > keys [ 0 ] , _pubring , cb_get_passphrase ) ;
}
if ( res = = ops_false )
2012-08-17 15:05:22 -04:00
std : : cerr < < " (WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures. " < < std : : endl ;
// also add self-signature if any (there should be!).
//
res = ops_validate_key_signatures ( result , & tmp_keyring - > keys [ 0 ] , tmp_keyring , cb_get_passphrase ) ;
if ( res = = ops_false )
std : : cerr < < " (WW) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures. " < < std : : endl ;
2012-08-13 15:37:50 -04:00
// Parse signers.
//
2012-08-17 15:05:22 -04:00
std : : set < std : : string > signers_set ; // Use a set to remove duplicates.
2012-08-13 15:37:50 -04:00
if ( result ! = NULL )
for ( size_t i = 0 ; i < result - > valid_count ; + + i )
{
std : : string signer_str = PGPIdType ( result - > valid_sigs [ i ] . signer_id ) . toStdString ( ) ;
2012-08-17 15:05:22 -04:00
signers_set . insert ( signer_str ) ;
2012-08-13 15:37:50 -04:00
}
ops_validate_result_free ( result ) ;
ops_keyring_free ( tmp_keyring ) ;
free ( tmp_keyring ) ;
2012-08-17 15:05:22 -04:00
// write to the output variable
signers . clear ( ) ;
for ( std : : set < std : : string > : : const_iterator it ( signers_set . begin ( ) ) ; it ! = signers_set . end ( ) ; + + it )
signers . push_back ( * it ) ;
2012-08-13 15:37:50 -04:00
return true ;
}
2012-07-12 15:20:31 -04:00
bool PGPHandler : : importGPGKeyPair ( const std : : string & filename , PGPIdType & imported_key_id , std : : string & import_error )
2012-07-10 17:40:53 -04:00
{
2012-07-12 15:20:31 -04:00
import_error = " " ;
2012-07-11 12:17:49 -04:00
// 1 - Test for file existance
//
2012-12-02 16:12:31 -05:00
FILE * ftest = RsDirUtil : : rs_fopen ( filename . c_str ( ) , " r " ) ;
2012-07-11 12:17:49 -04:00
if ( ftest = = NULL )
{
2012-07-12 15:20:31 -04:00
import_error = " Cannot open file " + filename + " for read. Please check access permissions. " ;
2012-07-11 12:17:49 -04:00
return false ;
}
fclose ( ftest ) ;
// 2 - Read keyring from supplied file.
//
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
if ( ops_false = = ops_keyring_read_from_file ( tmp_keyring , ops_true , filename . c_str ( ) ) )
{
2012-07-12 15:20:31 -04:00
import_error = " PGPHandler::readKeyRing(): cannot read key file. File corrupted? " ;
2012-07-11 12:17:49 -04:00
return false ;
}
if ( tmp_keyring - > nkeys ! = 2 )
{
2012-07-12 15:20:31 -04:00
import_error = " PGPHandler::importKeyPair(): file does not contain a valid keypair. " ;
if ( tmp_keyring - > nkeys > 2 )
import_error + = " \n Make sure that your key is a RSA key (DSA is not yet supported) and does not contain subkeys (not supported yet). " ;
2012-07-11 12:17:49 -04:00
return false ;
}
// 3 - Test that keyring contains a valid keypair.
//
const ops_keydata_t * pubkey = NULL ;
const ops_keydata_t * seckey = NULL ;
if ( tmp_keyring - > keys [ 0 ] . type = = OPS_PTAG_CT_PUBLIC_KEY )
pubkey = & tmp_keyring - > keys [ 0 ] ;
else if ( tmp_keyring - > keys [ 0 ] . type = = OPS_PTAG_CT_ENCRYPTED_SECRET_KEY )
seckey = & tmp_keyring - > keys [ 0 ] ;
else
{
2012-07-12 15:20:31 -04:00
import_error = " Unrecognised key type in key file for key #0. Giving up. " ;
2012-07-11 12:17:49 -04:00
std : : cerr < < " Unrecognised key type " < < tmp_keyring - > keys [ 0 ] . type < < " in key file for key #0. Giving up. " < < std : : endl ;
return false ;
}
if ( tmp_keyring - > keys [ 1 ] . type = = OPS_PTAG_CT_PUBLIC_KEY )
pubkey = & tmp_keyring - > keys [ 1 ] ;
else if ( tmp_keyring - > keys [ 1 ] . type = = OPS_PTAG_CT_ENCRYPTED_SECRET_KEY )
seckey = & tmp_keyring - > keys [ 1 ] ;
else
{
2012-07-12 15:20:31 -04:00
import_error = " Unrecognised key type in key file for key #1. Giving up. " ;
2012-07-11 12:17:49 -04:00
std : : cerr < < " Unrecognised key type " < < tmp_keyring - > keys [ 1 ] . type < < " in key file for key #1. Giving up. " < < std : : endl ;
return false ;
}
if ( pubkey = = NULL | | seckey = = NULL | | pubkey = = seckey )
{
2012-07-12 15:20:31 -04:00
import_error = " File does not contain a public and a private key. Sorry. " ;
2012-07-11 12:17:49 -04:00
return false ;
}
if ( memcmp ( pubkey - > fingerprint . fingerprint , seckey - > fingerprint . fingerprint , KEY_FINGERPRINT_SIZE ) ! = 0 )
{
2012-07-12 15:20:31 -04:00
import_error = " Public and private keys do nt have the same fingerprint. Sorry! " ;
return false ;
}
if ( pubkey - > key . pkey . version ! = 4 )
{
import_error = " Public key is not version 4. Rejected! " ;
2012-07-11 12:17:49 -04:00
return false ;
}
// 4 - now check self-signature for this keypair. For this we build a dummy keyring containing only the key.
//
ops_validate_result_t * result = ( ops_validate_result_t * ) ops_mallocz ( sizeof * result ) ;
ops_keyring_t dummy_keyring ;
dummy_keyring . nkeys = 1 ;
dummy_keyring . nkeys_allocated = 1 ;
dummy_keyring . keys = const_cast < ops_keydata_t * > ( pubkey ) ;
2012-08-07 15:16:17 -04:00
ops_validate_key_signatures ( result , const_cast < ops_keydata_t * > ( pubkey ) , & dummy_keyring , cb_get_passphrase ) ;
if ( result - > valid_count ! = 1 | | memcmp ( ( unsigned char * ) result - > valid_sigs [ 0 ] . signer_id , pubkey - > key_id , KEY_ID_SIZE ) )
2012-07-11 12:17:49 -04:00
{
2012-07-12 15:20:31 -04:00
import_error = " Cannot validate self signature for the imported key. Sorry. " ;
2012-07-11 12:17:49 -04:00
return false ;
}
ops_validate_result_free ( result ) ;
2013-07-25 16:05:31 -04:00
if ( ! RsDiscSpace : : checkForDiscSpace ( RS_PGP_DIRECTORY ) )
{
import_error = std : : string ( " (EE) low disc space in pgp directory. Can't write safely to keyring. " ) ;
return false ;
}
2012-07-11 12:17:49 -04:00
// 5 - All test passed. Adding key to keyring.
//
{
2013-06-09 09:09:36 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-07-11 12:17:49 -04:00
2013-06-09 09:09:36 -04:00
imported_key_id = PGPIdType ( pubkey - > key_id ) ;
2012-07-11 12:17:49 -04:00
2013-06-09 09:09:36 -04:00
if ( locked_getSecretKey ( imported_key_id ) = = NULL )
2012-07-11 12:17:49 -04:00
{
2013-06-09 09:09:36 -04:00
RsStackFileLock flck ( _pgp_lock_filename ) ; // lock access to PGP directory.
ops_create_info_t * cinfo = NULL ;
2013-07-25 16:05:31 -04:00
// Make a copy of the secret keyring
//
std : : string secring_path_tmp = _secring_path + " .tmp " ;
if ( RsDirUtil : : fileExists ( _secring_path ) & & ! RsDirUtil : : copyFile ( _secring_path , secring_path_tmp ) )
{
import_error = " (EE) Cannot write secret key to disk!! Disk full? Out of disk quota. Keyring will be left untouched. " ;
return false ;
}
// Append the new key
int fd = ops_setup_file_append ( & cinfo , secring_path_tmp . c_str ( ) ) ;
2013-06-09 09:09:36 -04:00
if ( ! ops_write_transferable_secret_key_from_packet_data ( seckey , ops_false , cinfo ) )
{
import_error = " (EE) Cannot encode secret key to disk!! Disk full? Out of disk quota? " ;
return false ;
}
ops_teardown_file_write ( cinfo , fd ) ;
2013-07-25 16:05:31 -04:00
// Rename the new keyring to overwrite the old one.
//
if ( ! RsDirUtil : : renameFile ( secring_path_tmp , _secring_path ) )
{
import_error = " (EE) Cannot move temp file " + secring_path_tmp + " . Bad write permissions? " ;
return false ;
}
2013-06-09 09:09:36 -04:00
addNewKeyToOPSKeyring ( _secring , * seckey ) ;
initCertificateInfo ( _secret_keyring_map [ imported_key_id . toStdString ( ) ] , seckey , _secring - > nkeys - 1 ) ;
2012-07-11 12:17:49 -04:00
}
2013-06-09 09:09:36 -04:00
else
import_error = " Private key already exists! Not importing it again. " ;
2012-08-07 15:16:17 -04:00
2013-06-09 09:09:36 -04:00
if ( locked_addOrMergeKey ( _pubring , _public_keyring_map , pubkey ) )
_pubring_changed = true ;
2012-07-11 12:17:49 -04:00
}
// 6 - clean
//
ops_keyring_free ( tmp_keyring ) ;
return true ;
2012-07-10 17:40:53 -04:00
}
2012-04-01 08:52:15 -04:00
void PGPHandler : : addNewKeyToOPSKeyring ( ops_keyring_t * kr , const ops_keydata_t & key )
{
2013-05-30 15:43:05 -04:00
if ( kr - > nkeys > = kr - > nkeys_allocated )
{
kr - > keys = ( ops_keydata_t * ) realloc ( kr - > keys , ( kr - > nkeys + 1 ) * sizeof ( ops_keydata_t ) ) ;
kr - > nkeys_allocated = kr - > nkeys + 1 ;
}
2012-04-01 08:52:15 -04:00
memset ( & kr - > keys [ kr - > nkeys ] , 0 , sizeof ( ops_keydata_t ) ) ;
ops_keydata_copy ( & kr - > keys [ kr - > nkeys ] , & key ) ;
kr - > nkeys + + ;
}
bool PGPHandler : : LoadCertificateFromString ( const std : : string & pgp_cert , PGPIdType & id , std : : string & error_string )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-15 17:58:46 -04:00
std : : cerr < < " Reading new key from string: " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-15 17:58:46 -04:00
2012-04-01 08:52:15 -04:00
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
ops_memory_t * mem = ops_memory_new ( ) ;
ops_memory_add ( mem , ( unsigned char * ) pgp_cert . c_str ( ) , pgp_cert . length ( ) ) ;
if ( ! ops_keyring_read_from_mem ( tmp_keyring , ops_true , mem ) )
{
ops_keyring_free ( tmp_keyring ) ;
2012-04-01 12:43:23 -04:00
free ( tmp_keyring ) ;
2012-04-01 08:52:15 -04:00
ops_memory_release ( mem ) ;
2012-04-01 12:43:23 -04:00
free ( mem ) ;
2012-04-01 08:52:15 -04:00
std : : cerr < < " Could not read key. Format error? " < < std : : endl ;
error_string = std : : string ( " Could not read key. Format error? " ) ;
return false ;
}
ops_memory_release ( mem ) ;
2012-04-01 12:43:23 -04:00
free ( mem ) ;
2012-04-01 08:52:15 -04:00
error_string . clear ( ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-15 17:58:46 -04:00
std : : cerr < < " Key read correctly: " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-04-01 08:52:15 -04:00
ops_keyring_list ( tmp_keyring ) ;
const ops_keydata_t * keydata = NULL ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( tmp_keyring , i + + ) ) ! = NULL )
2013-06-09 09:09:36 -04:00
if ( locked_addOrMergeKey ( _pubring , _public_keyring_map , keydata ) )
2012-07-01 18:24:37 -04:00
{
2012-06-29 15:38:19 -04:00
_pubring_changed = true ;
# ifdef DEBUG_PGPHANDLER
2012-07-01 18:24:37 -04:00
std : : cerr < < " Added the key in the main public keyring. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-07-01 18:24:37 -04:00
}
else
std : : cerr < < " Key already in public keyring. " < < std : : endl ;
2012-04-01 08:52:15 -04:00
2012-08-14 15:49:50 -04:00
if ( tmp_keyring - > nkeys > 0 )
id = PGPIdType ( tmp_keyring - > keys [ 0 ] . key_id ) ;
else
return false ;
2012-07-01 18:24:37 -04:00
2012-04-01 08:52:15 -04:00
ops_keyring_free ( tmp_keyring ) ;
2012-04-01 12:43:23 -04:00
free ( tmp_keyring ) ;
2012-06-12 16:31:13 -04:00
_pubring_changed = true ;
2012-04-01 08:52:15 -04:00
return true ;
}
2013-06-09 09:09:36 -04:00
bool PGPHandler : : locked_addOrMergeKey ( ops_keyring_t * keyring , std : : map < std : : string , PGPCertificateInfo > & kmap , const ops_keydata_t * keydata )
2012-04-08 10:52:01 -04:00
{
2012-06-29 15:38:19 -04:00
bool ret = false ;
PGPIdType id ( keydata - > key_id ) ;
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " AddOrMergeKey(): " < < std : : endl ;
std : : cerr < < " id: " < < id . toStdString ( ) < < std : : endl ;
# endif
// See if the key is already in the keyring
const ops_keydata_t * existing_key = NULL ;
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = kmap . find ( id . toStdString ( ) ) ;
// Checks that
// - the key is referenced by keyid
// - the map is initialized
// - the fingerprint matches!
//
if ( res = = kmap . end ( ) | | ( existing_key = ops_keyring_get_key_by_index ( keyring , res - > second . _key_index ) ) = = NULL )
{
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Key is new. Adding it to keyring " < < std : : endl ;
# endif
addNewKeyToOPSKeyring ( keyring , * keydata ) ; // the key is new.
initCertificateInfo ( kmap [ id . toStdString ( ) ] , keydata , keyring - > nkeys - 1 ) ;
existing_key = & ( keyring - > keys [ keyring - > nkeys - 1 ] ) ;
ret = true ;
}
else
{
if ( memcmp ( existing_key - > fingerprint . fingerprint , keydata - > fingerprint . fingerprint , KEY_FINGERPRINT_SIZE ) )
{
std : : cerr < < " (EE) attempt to merge key with identical id, but different fingerprint! " < < std : : endl ;
return false ;
}
2012-06-12 16:31:13 -04:00
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Key exists. Merging signatures. " < < std : : endl ;
# endif
ret = mergeKeySignatures ( const_cast < ops_keydata_t * > ( existing_key ) , keydata ) ;
2012-06-12 16:31:13 -04:00
2012-06-29 15:38:19 -04:00
if ( ret )
initCertificateInfo ( kmap [ id . toStdString ( ) ] , existing_key , res - > second . _key_index ) ;
}
2012-06-12 16:31:13 -04:00
2012-06-29 15:38:19 -04:00
if ( ret )
2013-05-31 08:42:16 -04:00
{
2012-06-29 15:38:19 -04:00
validateAndUpdateSignatures ( kmap [ id . toStdString ( ) ] , existing_key ) ;
2013-05-31 08:42:16 -04:00
kmap [ id . toStdString ( ) ] . _time_stamp = time ( NULL ) ;
}
2012-06-29 15:38:19 -04:00
return ret ;
2012-05-01 14:45:24 -04:00
}
2013-05-03 17:02:44 -04:00
// bool PGPHandler::encryptTextToString(const PGPIdType& key_id,const std::string& text,std::string& outstring)
// {
// RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
//
// const ops_keydata_t *public_key = getPublicKey(key_id) ;
//
// if(public_key == NULL)
// {
// std::cerr << "Cannot get public key of id " << key_id.toStdString() << std::endl;
// return false ;
// }
//
// if(public_key->type != OPS_PTAG_CT_PUBLIC_KEY)
// {
// std::cerr << "PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key!" << std::endl;
// return false ;
// }
//
// ops_create_info_t *info;
// ops_memory_t *buf = NULL ;
// ops_setup_memory_write(&info, &buf, 0);
//
// ops_encrypt_stream(info, public_key, NULL, ops_false, ops_true);
// ops_write(text.c_str(), text.length(), info);
// ops_writer_close(info);
//
// outstring = std::string((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ;
// ops_create_info_delete(info);
//
// return true ;
// }
2012-05-01 14:45:24 -04:00
bool PGPHandler : : encryptTextToFile ( const PGPIdType & key_id , const std : : string & text , const std : : string & outfile )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * public_key = locked_getPublicKey ( key_id , true ) ;
2012-04-08 10:52:01 -04:00
if ( public_key = = NULL )
{
std : : cerr < < " Cannot get public key of id " < < key_id . toStdString ( ) < < std : : endl ;
return false ;
}
2012-07-01 10:34:11 -04:00
if ( public_key - > type ! = OPS_PTAG_CT_PUBLIC_KEY )
{
2013-07-25 16:05:31 -04:00
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key! " < < std : : endl ;
2012-07-01 10:34:11 -04:00
return false ;
}
2013-07-26 19:12:09 -04:00
std : : string outfile_tmp = outfile + " .tmp " ;
ops_create_info_t * info ;
int fd = ops_setup_file_write ( & info , outfile_tmp . c_str ( ) , ops_true ) ;
if ( fd < 0 )
2012-04-08 10:52:01 -04:00
{
2013-07-25 16:05:31 -04:00
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: Cannot write to " < < outfile_tmp < < std : : endl ;
2012-04-08 10:52:01 -04:00
return false ;
}
2013-07-26 19:12:09 -04:00
2012-04-08 10:52:01 -04:00
ops_encrypt_stream ( info , public_key , NULL , ops_false , ops_true ) ;
ops_write ( text . c_str ( ) , text . length ( ) , info ) ;
2013-07-26 19:12:09 -04:00
ops_teardown_file_write ( info , fd ) ;
2012-04-08 10:52:01 -04:00
2013-07-25 16:05:31 -04:00
if ( ! RsDirUtil : : renameFile ( outfile_tmp , outfile ) )
{
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: Cannot rename " + outfile_tmp + " to " + outfile + " . Disk error? " < < std : : endl ;
return false ;
}
2012-04-08 10:52:01 -04:00
return true ;
}
2013-04-10 16:28:13 -04:00
bool PGPHandler : : encryptDataBin ( const PGPIdType & key_id , const void * data , const uint32_t len , unsigned char * encrypted_data , unsigned int * encrypted_data_len )
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-06-06 15:58:30 -04:00
const ops_keydata_t * public_key = locked_getPublicKey ( key_id , true ) ;
2013-04-10 16:28:13 -04:00
if ( public_key = = NULL )
{
std : : cerr < < " Cannot get public key of id " < < key_id . toStdString ( ) < < std : : endl ;
return false ;
}
if ( public_key - > type ! = OPS_PTAG_CT_PUBLIC_KEY )
{
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: supplied id did not return a public key! " < < std : : endl ;
return false ;
}
2013-06-11 16:51:39 -04:00
if ( public_key - > key . pkey . algorithm ! = OPS_PKA_RSA )
{
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: supplied key id " < < key_id . toStdString ( ) < < " is not an RSA key (DSA for instance, is not supported)! " < < std : : endl ;
return false ;
}
2013-04-10 16:28:13 -04:00
ops_create_info_t * info ;
ops_memory_t * buf = NULL ;
ops_setup_memory_write ( & info , & buf , 0 ) ;
ops_encrypt_stream ( info , public_key , NULL , ops_false , ops_false ) ;
ops_write ( data , len , info ) ;
ops_writer_close ( info ) ;
ops_create_info_delete ( info ) ;
int tlen = ops_memory_get_length ( buf ) ;
2013-04-10 17:21:52 -04:00
bool res ;
2013-04-18 17:41:13 -04:00
if ( ( int ) * encrypted_data_len > = tlen )
2013-04-10 17:21:52 -04:00
{
memcpy ( encrypted_data , ops_memory_get_data ( buf ) , tlen ) ;
* encrypted_data_len = tlen ;
res = true ;
}
else
{
std : : cerr < < " Not enough room to fit encrypted data. Size given= " < < * encrypted_data_len < < " , required= " < < tlen < < std : : endl ;
res = false ;
}
2013-04-10 16:28:13 -04:00
ops_memory_release ( buf ) ;
free ( buf ) ;
2013-04-10 17:21:52 -04:00
return res ;
2013-04-10 16:28:13 -04:00
}
2013-06-09 13:54:54 -04:00
bool PGPHandler : : decryptDataBin ( const PGPIdType & /*key_id*/ , const void * encrypted_data , const uint32_t encrypted_len , unsigned char * data , unsigned int * data_len )
2013-04-10 16:28:13 -04:00
{
2013-04-18 17:41:13 -04:00
int out_length ;
unsigned char * out ;
ops_boolean_t res = ops_decrypt_memory ( ( const unsigned char * ) encrypted_data , encrypted_len , & out , & out_length , _secring , ops_false , cb_get_passphrase ) ;
2013-07-06 15:59:42 -04:00
if ( * data_len < ( unsigned int ) out_length )
2013-04-18 17:41:13 -04:00
{
std : : cerr < < " Not enough room to store decrypted data! Please give more. " < < std : : endl ;
return false ;
}
2013-07-06 15:59:42 -04:00
* data_len = ( unsigned int ) out_length ;
2013-04-18 17:41:13 -04:00
memcpy ( data , out , out_length ) ;
free ( out ) ;
return ( bool ) res ;
2013-04-10 16:28:13 -04:00
}
2012-07-11 12:17:49 -04:00
bool PGPHandler : : decryptTextFromFile ( const PGPIdType & , std : : string & text , const std : : string & inputfile )
2012-04-08 10:52:01 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-04-08 10:52:01 -04:00
unsigned char * out_buf = NULL ;
std : : string buf ;
2012-12-02 16:12:31 -05:00
FILE * f = RsDirUtil : : rs_fopen ( inputfile . c_str ( ) , " rb " ) ;
2012-04-08 10:52:01 -04:00
2012-06-14 18:53:02 -04:00
if ( f = = NULL )
{
2012-08-07 15:16:17 -04:00
std : : cerr < < " Cannot open file " < < inputfile < < " for read. " < < std : : endl ;
2012-06-14 18:53:02 -04:00
return false ;
}
2012-07-23 17:42:16 -04:00
int c ;
while ( ( c = fgetc ( f ) ) ! = EOF )
buf + = ( unsigned char ) c ;
2012-04-08 10:52:01 -04:00
fclose ( f ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-04-22 07:36:34 -04:00
std : : cerr < < " PGPHandler::decryptTextFromFile: read a file of length " < < std : : dec < < buf . length ( ) < < std : : endl ;
std : : cerr < < " buf= \" " < < buf < < " \" " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-04-08 10:52:01 -04:00
int out_length ;
ops_boolean_t res = ops_decrypt_memory ( ( const unsigned char * ) buf . c_str ( ) , buf . length ( ) , & out_buf , & out_length , _secring , ops_true , cb_get_passphrase ) ;
text = std : : string ( ( char * ) out_buf , out_length ) ;
2012-06-14 18:53:02 -04:00
free ( out_buf ) ;
2012-04-08 10:52:01 -04:00
return ( bool ) res ;
}
2013-03-22 19:54:54 -04:00
bool PGPHandler : : SignDataBin ( const PGPIdType & id , const void * data , const uint32_t len , unsigned char * sign , unsigned int * signlen , bool use_raw_signature )
2012-04-01 08:52:15 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-04-01 08:52:15 -04:00
// need to find the key and to decrypt it.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * key = locked_getSecretKey ( id ) ;
2012-04-01 08:52:15 -04:00
if ( ! key )
{
std : : cerr < < " Cannot sign: no secret key with id " < < id . toStdString ( ) < < std : : endl ;
return false ;
}
2012-09-13 15:18:55 -04:00
std : : string uid_hint ;
if ( key - > nuids > 0 )
uid_hint = std : : string ( ( const char * ) key - > uids [ 0 ] . user_id ) ;
uid_hint + = " ( " + PGPIdType ( key - > key_id ) . toStdString ( ) + " ) " ;
2013-03-22 18:01:58 -04:00
# ifdef DEBUG_PGPHANDLER
ops_fingerprint_t f ;
ops_fingerprint ( & f , & key - > key . pkey ) ;
PGPFingerprintType fp ( f . fingerprint ) ;
# endif
2012-09-13 15:18:55 -04:00
std : : string passphrase = _passphrase_callback ( NULL , uid_hint . c_str ( ) , " Please enter passwd for encrypting your key : " , false ) ;
2012-04-01 08:52:15 -04:00
ops_secret_key_t * secret_key = ops_decrypt_secret_key_from_data ( key , passphrase . c_str ( ) ) ;
if ( ! secret_key )
{
std : : cerr < < " Key decryption went wrong. Wrong passwd? " < < std : : endl ;
return false ;
}
// then do the signature.
2013-03-22 19:54:54 -04:00
ops_boolean_t not_raw = ! use_raw_signature ;
ops_memory_t * memres = ops_sign_buf ( data , len , ( ops_sig_type_t ) 0x00 , secret_key , ops_false , ops_false , not_raw , not_raw ) ;
2012-04-01 08:52:15 -04:00
if ( ! memres )
return false ;
2013-04-10 17:21:52 -04:00
bool res ;
uint32_t slen = ( uint32_t ) ops_memory_get_length ( memres ) ;
2012-04-01 08:52:15 -04:00
2013-04-10 17:21:52 -04:00
if ( * signlen > = slen )
{
* signlen = slen ;
memcpy ( sign , ops_memory_get_data ( memres ) , * signlen ) ;
res = true ;
}
else
{
std : : cerr < < " (EE) memory chunk is not large enough for signature packet. Requred size: " < < slen < < " bytes. " < < std : : endl ;
res = false ;
}
2012-04-01 08:52:15 -04:00
2012-04-01 12:43:23 -04:00
ops_memory_release ( memres ) ;
free ( memres ) ;
ops_secret_key_free ( secret_key ) ;
free ( secret_key ) ;
2013-03-22 18:01:58 -04:00
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Signed with fingerprint " < < fp . toStdString ( ) < < " , length " < < std : : dec < < * signlen < < " , literal data length = " < < len < < std : : endl ;
std : : cerr < < " Signature body: " < < std : : endl ;
hexdump ( ( unsigned char * ) data , len ) ;
std : : cerr < < std : : endl ;
std : : cerr < < " Data: " < < std : : endl ;
hexdump ( ( unsigned char * ) sign , * signlen ) ;
std : : cerr < < std : : endl ;
# endif
2013-04-10 17:21:52 -04:00
return res ;
2012-04-01 08:52:15 -04:00
}
2012-07-05 18:25:46 -04:00
bool PGPHandler : : privateSignCertificate ( const PGPIdType & ownId , const PGPIdType & id_of_key_to_sign )
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
ops_keydata_t * key_to_sign = const_cast < ops_keydata_t * > ( locked_getPublicKey ( id_of_key_to_sign , true ) ) ;
2012-07-05 18:25:46 -04:00
if ( key_to_sign = = NULL )
{
std : : cerr < < " Cannot sign: no public key with id " < < id_of_key_to_sign . toStdString ( ) < < std : : endl ;
return false ;
}
// 1 - get decrypted secret key
//
2013-05-21 18:38:00 -04:00
const ops_keydata_t * skey = locked_getSecretKey ( ownId ) ;
2012-07-05 18:25:46 -04:00
if ( ! skey )
{
std : : cerr < < " Cannot sign: no secret key with id " < < ownId . toStdString ( ) < < std : : endl ;
return false ;
}
2013-05-21 18:38:00 -04:00
const ops_keydata_t * pkey = locked_getPublicKey ( ownId , true ) ;
2012-07-05 18:25:46 -04:00
if ( ! pkey )
{
std : : cerr < < " Cannot sign: no public key with id " < < ownId . toStdString ( ) < < std : : endl ;
return false ;
}
std : : string passphrase = _passphrase_callback ( NULL , PGPIdType ( skey - > key_id ) . toStdString ( ) . c_str ( ) , " Please enter passwd for encrypting your key : " , false ) ;
ops_secret_key_t * secret_key = ops_decrypt_secret_key_from_data ( skey , passphrase . c_str ( ) ) ;
if ( ! secret_key )
{
std : : cerr < < " Key decryption went wrong. Wrong passwd? " < < std : : endl ;
return false ;
}
// 2 - then do the signature.
2012-07-11 12:17:49 -04:00
if ( ! ops_sign_key ( key_to_sign , pkey - > key_id , secret_key ) )
{
std : : cerr < < " Key signature went wrong. Wrong passwd? " < < std : : endl ;
return false ;
}
2012-07-05 18:25:46 -04:00
// 3 - free memory
//
ops_secret_key_free ( secret_key ) ;
free ( secret_key ) ;
_pubring_changed = true ;
2012-07-07 12:26:54 -04:00
// 4 - update signatures.
//
PGPCertificateInfo & cert ( _public_keyring_map [ id_of_key_to_sign . toStdString ( ) ] ) ;
validateAndUpdateSignatures ( cert , key_to_sign ) ;
2012-07-13 08:20:44 -04:00
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ;
2012-07-07 12:26:54 -04:00
2012-07-05 18:25:46 -04:00
return true ;
}
2012-07-13 08:20:44 -04:00
void PGPHandler : : updateOwnSignatureFlag ( const PGPIdType & own_id )
{
2013-06-09 09:09:36 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-07-13 08:20:44 -04:00
std : : string own_id_str = own_id . toStdString ( ) ;
2013-06-09 09:09:36 -04:00
PGPCertificateInfo & own_cert ( _public_keyring_map [ own_id_str ] ) ;
2012-07-13 08:20:44 -04:00
for ( std : : map < std : : string , PGPCertificateInfo > : : iterator it = _public_keyring_map . begin ( ) ; it ! = _public_keyring_map . end ( ) ; + + it )
2013-06-09 09:09:36 -04:00
locked_updateOwnSignatureFlag ( it - > second , it - > first , own_cert , own_id_str ) ;
}
void PGPHandler : : updateOwnSignatureFlag ( const PGPIdType & cert_id , const PGPIdType & own_id )
{
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
std : : map < std : : string , PGPCertificateInfo > : : iterator it ( _public_keyring_map . find ( cert_id . toStdString ( ) ) ) ;
if ( it = = _public_keyring_map . end ( ) )
{
std : : cerr < < " updateOwnSignatureFlag: Cannot get certificate for string " < < cert_id . toStdString ( ) < < " . This is probably a bug. " < < std : : endl ;
return ;
}
PGPCertificateInfo & cert ( it - > second ) ;
std : : string own_id_str = own_id . toStdString ( ) ;
PGPCertificateInfo & own_cert ( _public_keyring_map [ own_id_str ] ) ;
locked_updateOwnSignatureFlag ( cert , cert_id . toStdString ( ) , own_cert , own_id_str ) ;
}
void PGPHandler : : locked_updateOwnSignatureFlag ( PGPCertificateInfo & cert , const std : : string & cert_id_str , PGPCertificateInfo & own_cert , const std : : string & own_id_str )
{
if ( cert . signers . find ( own_id_str ) ! = cert . signers . end ( ) )
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ;
else
cert . _flags & = ~ PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ;
if ( own_cert . signers . find ( cert_id_str ) ! = own_cert . signers . end ( ) )
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ;
else
cert . _flags & = ~ PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME ;
2012-07-13 08:20:44 -04:00
}
2012-04-04 15:27:07 -04:00
bool PGPHandler : : getKeyFingerprint ( const PGPIdType & id , PGPFingerprintType & fp ) const
2012-04-01 17:10:54 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2013-05-21 18:38:00 -04:00
const ops_keydata_t * key = locked_getPublicKey ( id , false ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
if ( key = = NULL )
return false ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
ops_fingerprint_t f ;
ops_fingerprint ( & f , & key - > key . pkey ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
fp = PGPFingerprintType ( f . fingerprint ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
return true ;
}
2012-04-26 15:37:15 -04:00
bool PGPHandler : : VerifySignBin ( const void * literal_data , uint32_t literal_data_length , unsigned char * sign , unsigned int sign_len , const PGPFingerprintType & key_fingerprint )
2012-04-04 15:27:07 -04:00
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-06-06 16:31:19 -04:00
PGPIdType id = PGPIdType ( key_fingerprint . toByteArray ( ) + PGPFingerprintType : : SIZE_IN_BYTES - PGPIdType : : SIZE_IN_BYTES ) ;
2013-05-21 18:38:00 -04:00
const ops_keydata_t * key = locked_getPublicKey ( id , true ) ;
2012-04-04 15:27:07 -04:00
if ( key = = NULL )
{
std : : cerr < < " No key returned by fingerprint " < < key_fingerprint . toStdString ( ) < < " , and ID " < < id . toStdString ( ) < < " , signature verification failed! " < < std : : endl ;
return false ;
}
// Check that fingerprint is the same.
const ops_public_key_t * pkey = & key - > key . pkey ;
ops_fingerprint_t fp ;
ops_fingerprint ( & fp , pkey ) ;
if ( key_fingerprint ! = PGPFingerprintType ( fp . fingerprint ) )
{
std : : cerr < < " Key fingerprint does not match " < < key_fingerprint . toStdString ( ) < < " , for ID " < < id . toStdString ( ) < < " , signature verification failed! " < < std : : endl ;
return false ;
}
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-04-26 17:39:45 -04:00
std : : cerr < < " Verifying signature from fingerprint " < < key_fingerprint . toStdString ( ) < < " , length " < < std : : dec < < sign_len < < " , literal data length = " < < literal_data_length < < std : : endl ;
2012-07-09 16:20:36 -04:00
std : : cerr < < " Signature body: " < < std : : endl ;
2013-03-22 18:01:58 -04:00
hexdump ( ( unsigned char * ) sign , sign_len ) ;
std : : cerr < < std : : endl ;
std : : cerr < < " Signed data: " < < std : : endl ;
hexdump ( ( unsigned char * ) literal_data , literal_data_length ) ;
2012-07-09 16:20:36 -04:00
std : : cerr < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-04-04 15:27:07 -04:00
2012-04-26 15:37:15 -04:00
return ops_validate_detached_signature ( literal_data , literal_data_length , sign , sign_len , key ) ;
2012-04-01 17:10:54 -04:00
}
2012-04-09 13:03:47 -04:00
void PGPHandler : : setAcceptConnexion ( const PGPIdType & id , bool b )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : iterator res = _public_keyring_map . find ( id . toStdString ( ) ) ;
if ( res ! = _public_keyring_map . end ( ) )
2012-04-29 07:57:03 -04:00
{
2012-04-09 13:03:47 -04:00
if ( b )
res - > second . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ;
else
res - > second . _flags & = ~ PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ;
2012-04-29 07:57:03 -04:00
}
2012-04-09 13:03:47 -04:00
}
bool PGPHandler : : getGPGFilteredList ( std : : list < PGPIdType > & list , bool ( * filter ) ( const PGPCertificateInfo & ) ) const
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP directory.
2012-04-09 13:03:47 -04:00
list . clear ( ) ;
for ( std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . begin ( ) ) ; it ! = _public_keyring_map . end ( ) ; + + it )
if ( filter = = NULL | | ( * filter ) ( it - > second ) )
2012-06-06 16:31:19 -04:00
list . push_back ( PGPIdType ( it - > first ) ) ;
2012-04-09 13:03:47 -04:00
return true ;
}
bool PGPHandler : : isGPGId ( const std : : string & id )
{
return _public_keyring_map . find ( id ) ! = _public_keyring_map . end ( ) ;
}
bool PGPHandler : : isGPGSigned ( const std : : string & id )
{
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id ) ;
return res ! = _public_keyring_map . end ( ) & & ( res - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ) ;
}
bool PGPHandler : : isGPGAccepted ( const std : : string & id )
{
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id ) ;
2012-04-26 17:39:45 -04:00
return ( res ! = _public_keyring_map . end ( ) ) & & ( res - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ) ;
2012-04-09 13:03:47 -04:00
}
2012-06-15 17:58:46 -04:00
// Lexicographic order on signature packets
//
bool operator < ( const ops_packet_t & p1 , const ops_packet_t & p2 )
{
if ( p1 . length < p2 . length )
return true ;
if ( p1 . length > p2 . length )
return false ;
2012-06-29 15:38:19 -04:00
for ( uint32_t i = 0 ; i < p1 . length ; + + i )
2012-06-15 17:58:46 -04:00
{
if ( p1 . raw [ i ] < p2 . raw [ i ] )
return true ;
if ( p1 . raw [ i ] > p2 . raw [ i ] )
return false ;
}
return false ;
}
bool PGPHandler : : mergeKeySignatures ( ops_keydata_t * dst , const ops_keydata_t * src )
{
// First sort all signatures into lists to see which is new, which is not new
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-15 17:58:46 -04:00
std : : cerr < < " Merging signatures for key " < < PGPIdType ( dst - > key_id ) . toStdString ( ) < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-15 17:58:46 -04:00
std : : set < ops_packet_t > dst_packets ;
2012-06-29 15:38:19 -04:00
for ( uint32_t i = 0 ; i < dst - > npackets ; + + i ) dst_packets . insert ( dst - > packets [ i ] ) ;
2012-06-15 17:58:46 -04:00
std : : set < ops_packet_t > to_add ;
2012-06-29 15:38:19 -04:00
for ( uint32_t i = 0 ; i < src - > npackets ; + + i )
2012-06-15 17:58:46 -04:00
if ( dst_packets . find ( src - > packets [ i ] ) = = dst_packets . end ( ) )
{
uint8_t tag ;
uint32_t length ;
2012-09-01 16:02:39 -04:00
unsigned char * tmp_data = src - > packets [ i ] . raw ; // put it in a tmp variable because read_packetHeader() will modify it!!
2012-06-15 17:58:46 -04:00
2012-09-01 16:02:39 -04:00
PGPKeyParser : : read_packetHeader ( tmp_data , tag , length ) ;
2012-06-15 17:58:46 -04:00
if ( tag = = PGPKeyParser : : PGP_PACKET_TAG_SIGNATURE )
to_add . insert ( src - > packets [ i ] ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-15 17:58:46 -04:00
else
std : : cerr < < " Packet with tag 0x " < < std : : hex < < ( int ) ( src - > packets [ i ] . raw [ 0 ] ) < < std : : dec < < " not merged, because it is not a signature. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-15 17:58:46 -04:00
}
for ( std : : set < ops_packet_t > : : const_iterator it ( to_add . begin ( ) ) ; it ! = to_add . end ( ) ; + + it )
{
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-15 17:58:46 -04:00
std : : cerr < < " Adding packet with tag 0x " < < std : : hex < < ( int ) ( * it ) . raw [ 0 ] < < std : : dec < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-15 17:58:46 -04:00
ops_add_packet_to_keydata ( dst , & * it ) ;
}
return to_add . size ( ) > 0 ;
}
2012-06-29 15:38:19 -04:00
bool PGPHandler : : privateTrustCertificate ( const PGPIdType & id , int trustlvl )
2012-06-20 17:59:04 -04:00
{
2012-06-29 15:38:19 -04:00
if ( trustlvl < 0 | | trustlvl > = 6 | | trustlvl = = 1 )
2012-06-20 17:59:04 -04:00
{
std : : cerr < < " Invalid trust level " < < trustlvl < < " passed to privateTrustCertificate. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
return false ;
2012-06-20 17:59:04 -04:00
}
std : : map < std : : string , PGPCertificateInfo > : : iterator it = _public_keyring_map . find ( id . toStdString ( ) ) ;
if ( it = = _public_keyring_map . end ( ) )
{
std : : cerr < < " (EE) Key id " < < id . toStdString ( ) < < " not in the keyring. Can't setup trust level. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
return false ;
2012-06-20 17:59:04 -04:00
}
2012-07-07 12:26:54 -04:00
if ( ( int ) it - > second . _trustLvl ! = trustlvl )
2012-06-20 17:59:04 -04:00
_trustdb_changed = true ;
2012-07-07 12:26:54 -04:00
it - > second . _trustLvl = trustlvl ;
2012-06-29 15:38:19 -04:00
return true ;
2012-06-20 17:59:04 -04:00
}
struct PrivateTrustPacket
{
unsigned char user_id [ KEY_ID_SIZE ] ; // pgp id in unsigned char format.
uint8_t trust_level ; // trust level. From 0 to 6.
2013-05-21 18:38:00 -04:00
uint32_t time_stamp ; // last time the cert was ever used, in seconds since the epoch. 0 means not initialized.
2012-06-20 17:59:04 -04:00
} ;
void PGPHandler : : locked_readPrivateTrustDatabase ( )
{
2012-12-02 16:12:31 -05:00
FILE * fdb = RsDirUtil : : rs_fopen ( _trustdb_path . c_str ( ) , " rb " ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-20 17:59:04 -04:00
std : : cerr < < " PGPHandler: Reading private trust database. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-20 17:59:04 -04:00
if ( fdb = = NULL )
{
std : : cerr < < " private trust database not found. No trust info loaded. " < < std : : endl ;
return ;
}
std : : map < std : : string , PGPCertificateInfo > : : iterator it ;
PrivateTrustPacket trustpacket ;
2012-07-07 12:26:54 -04:00
int n_packets = 0 ;
2012-06-20 17:59:04 -04:00
while ( fread ( ( void * ) & trustpacket , sizeof ( PrivateTrustPacket ) , 1 , fdb ) = = 1 )
{
it = _public_keyring_map . find ( PGPIdType ( trustpacket . user_id ) . toStdString ( ) ) ;
if ( it = = _public_keyring_map . end ( ) )
{
std : : cerr < < " (WW) Trust packet found for unknown key id " < < PGPIdType ( trustpacket . user_id ) . toStdString ( ) < < std : : endl ;
continue ;
}
if ( trustpacket . trust_level > 6 )
{
std : : cerr < < " (WW) Trust packet found with unexpected trust level " < < trustpacket . trust_level < < std : : endl ;
continue ;
}
2012-07-07 12:26:54 -04:00
+ + n_packets ;
it - > second . _trustLvl = trustpacket . trust_level ;
2013-05-31 04:13:16 -04:00
if ( trustpacket . time_stamp > it - > second . _time_stamp ) // only update time stamp if the loaded time stamp is newer
it - > second . _time_stamp = trustpacket . time_stamp ;
2012-06-20 17:59:04 -04:00
}
fclose ( fdb ) ;
2012-07-07 12:26:54 -04:00
std : : cerr < < " PGPHandler: Successfully read " < < n_packets < < " trust packets. " < < std : : endl ;
2012-06-20 17:59:04 -04:00
}
2012-06-29 15:38:19 -04:00
bool PGPHandler : : locked_writePrivateTrustDatabase ( )
2012-06-20 17:59:04 -04:00
{
2012-12-02 16:12:31 -05:00
FILE * fdb = RsDirUtil : : rs_fopen ( ( _trustdb_path + " .tmp " ) . c_str ( ) , " wb " ) ;
2012-06-29 15:38:19 -04:00
# ifdef DEBUG_PGPHANDLER
2012-06-20 17:59:04 -04:00
std : : cerr < < " PGPHandler: Reading private trust database. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
# endif
2012-06-20 17:59:04 -04:00
if ( fdb = = NULL )
{
std : : cerr < < " (EE) Can't open private trust database file " < < _trustdb_path < < " for write. Giving up! " < < std : : endl ;
2012-06-29 15:38:19 -04:00
return false ;
2012-06-20 17:59:04 -04:00
}
PrivateTrustPacket trustpacket ;
for ( std : : map < std : : string , PGPCertificateInfo > : : iterator it = _public_keyring_map . begin ( ) ; it ! = _public_keyring_map . end ( ) ; + + it )
{
memcpy ( & trustpacket . user_id , PGPIdType ( it - > first ) . toByteArray ( ) , KEY_ID_SIZE ) ;
2012-07-07 12:26:54 -04:00
trustpacket . trust_level = it - > second . _trustLvl ;
2013-05-21 18:38:00 -04:00
trustpacket . time_stamp = it - > second . _time_stamp ;
2012-06-20 17:59:04 -04:00
if ( fwrite ( ( void * ) & trustpacket , sizeof ( PrivateTrustPacket ) , 1 , fdb ) ! = 1 )
{
std : : cerr < < " (EE) Cannot write to trust database " < < _trustdb_path < < " . Disc full, or quota exceeded ? Leaving database untouched. " < < std : : endl ;
fclose ( fdb ) ;
2012-06-29 15:38:19 -04:00
return false ;
2012-06-20 17:59:04 -04:00
}
}
fclose ( fdb ) ;
if ( ! RsDirUtil : : renameFile ( _trustdb_path + " .tmp " , _trustdb_path ) )
2012-06-29 15:38:19 -04:00
{
2012-06-20 17:59:04 -04:00
std : : cerr < < " (EE) Cannot move temp file " < < _trustdb_path + " .tmp " < < " . Bad write permissions? " < < std : : endl ;
2012-06-29 15:38:19 -04:00
return false ;
}
else
return true ;
}
bool PGPHandler : : syncDatabase ( )
{
2012-07-05 18:25:46 -04:00
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
2012-06-29 15:38:19 -04:00
RsStackFileLock flck ( _pgp_lock_filename ) ; // lock access to PGP directory.
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Sync-ing keyrings. " < < std : : endl ;
# endif
locked_syncPublicKeyring ( ) ;
2012-07-01 17:40:44 -04:00
//locked_syncSecretKeyring() ;
2012-06-29 15:38:19 -04:00
// Now sync the trust database as well.
//
locked_syncTrustDatabase ( ) ;
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Done. " < < std : : endl ;
# endif
return true ;
2012-06-20 17:59:04 -04:00
}
2012-06-15 17:58:46 -04:00
2012-06-29 15:38:19 -04:00
bool PGPHandler : : locked_syncPublicKeyring ( )
{
struct stat64 buf ;
# ifdef WINDOWS_SYS
std : : wstring wfullname ;
librs : : util : : ConvertUtf8ToUtf16 ( _pubring_path , wfullname ) ;
if ( - 1 = = _wstati64 ( wfullname . c_str ( ) , & buf ) )
# else
2012-07-01 10:34:11 -04:00
if ( - 1 = = stat64 ( _pubring_path . c_str ( ) , & buf ) )
2012-06-29 15:38:19 -04:00
# endif
2012-07-01 10:34:11 -04:00
std : : cerr < < " PGPHandler::syncDatabase(): can't stat file " < < _pubring_path < < " . Can't sync public keyring. " < < std : : endl ;
2012-06-29 15:38:19 -04:00
if ( _pubring_last_update_time < buf . st_mtime )
{
std : : cerr < < " Detected change on disk of public keyring. Merging! " < < std : : endl ;
2013-06-09 09:09:36 -04:00
locked_mergeKeyringFromDisk ( _pubring , _public_keyring_map , _pubring_path ) ;
2012-06-29 15:38:19 -04:00
_pubring_last_update_time = buf . st_mtime ;
}
// Now check if the pubring was locally modified, which needs saving it again
2013-07-25 16:05:31 -04:00
if ( _pubring_changed & & RsDiscSpace : : checkForDiscSpace ( RS_PGP_DIRECTORY ) )
2012-06-29 15:38:19 -04:00
{
2012-09-01 10:09:20 -04:00
std : : string tmp_keyring_file = _pubring_path + " .tmp " ;
2012-06-29 15:38:19 -04:00
std : : cerr < < " Local changes in public keyring. Writing to disk... " < < std : : endl ;
2012-09-01 10:09:20 -04:00
if ( ! ops_write_keyring_to_file ( _pubring , ops_false , tmp_keyring_file . c_str ( ) , ops_true ) )
2012-06-29 15:38:19 -04:00
{
2012-09-01 10:09:20 -04:00
std : : cerr < < " Cannot write public keyring tmp file. Disk full? Disk quota exceeded? " < < std : : endl ;
return false ;
2012-06-29 15:38:19 -04:00
}
2012-09-01 10:09:20 -04:00
if ( ! RsDirUtil : : renameFile ( tmp_keyring_file , _pubring_path ) )
{
std : : cerr < < " Cannot rename tmp pubring file " < < tmp_keyring_file < < " into actual pubring file " < < _pubring_path < < " . Check writing permissions?!? " < < std : : endl ;
return false ;
}
std : : cerr < < " Done. " < < std : : endl ;
_pubring_last_update_time = time ( NULL ) ; // should we get this value from the disk instead??
_pubring_changed = false ;
2012-06-29 15:38:19 -04:00
}
return true ;
}
bool PGPHandler : : locked_syncTrustDatabase ( )
{
struct stat64 buf ;
std : : wstring wfullname ;
# ifdef WINDOWS_SYS
librs : : util : : ConvertUtf8ToUtf16 ( _trustdb_path , wfullname ) ;
if ( - 1 = = _wstati64 ( wfullname . c_str ( ) , & buf ) )
# else
if ( - 1 = = stat64 ( _trustdb_path . c_str ( ) , & buf ) )
# endif
{
std : : cerr < < " PGPHandler::syncDatabase(): can't stat file " < < _trustdb_path < < " . Will force write it. " < < std : : endl ;
_trustdb_changed = true ; // we force write of trust database if it does not exist.
}
if ( _trustdb_last_update_time < buf . st_mtime )
{
std : : cerr < < " Detected change on disk of trust database. " < < std : : endl ;
locked_readPrivateTrustDatabase ( ) ;
_trustdb_last_update_time = time ( NULL ) ;
}
if ( _trustdb_changed )
{
std : : cerr < < " Local changes in trust database. Writing to disk... " < < std : : endl ;
if ( ! locked_writePrivateTrustDatabase ( ) )
std : : cerr < < " Cannot write trust database. Disk full? Disk quota exceeded? " < < std : : endl ;
else
{
std : : cerr < < " Done. " < < std : : endl ;
_trustdb_last_update_time = time ( NULL ) ;
_trustdb_changed = false ;
}
}
return true ;
}
2013-06-09 09:09:36 -04:00
void PGPHandler : : locked_mergeKeyringFromDisk ( ops_keyring_t * keyring ,
2012-06-29 15:38:19 -04:00
std : : map < std : : string , PGPCertificateInfo > & kmap ,
const std : : string & keyring_file )
{
# ifdef DEBUG_PGPHANDLER
std : : cerr < < " Merging keyring " < < keyring_file < < " from disk to memory. " < < std : : endl ;
# endif
// 1 - load keyring into a temporary keyring list.
ops_keyring_t * tmp_keyring = PGPHandler : : allocateOPSKeyring ( ) ;
if ( ops_false = = ops_keyring_read_from_file ( tmp_keyring , false , keyring_file . c_str ( ) ) )
{
2013-06-09 09:09:36 -04:00
std : : cerr < < " PGPHandler::locked_mergeKeyringFromDisk(): cannot read keyring. File corrupted? " ;
2012-06-29 15:38:19 -04:00
ops_keyring_free ( tmp_keyring ) ;
return ;
}
// 2 - load new keys and merge existing key signatures
for ( int i = 0 ; i < tmp_keyring - > nkeys ; + + i )
2013-06-09 09:09:36 -04:00
locked_addOrMergeKey ( keyring , kmap , & tmp_keyring - > keys [ i ] ) ; // we dont' account for the return value. This is disk merging, not local changes.
2012-06-29 15:38:19 -04:00
// 4 - clean
ops_keyring_free ( tmp_keyring ) ;
}
2013-05-29 17:32:02 -04:00
bool PGPHandler : : removeKeysFromPGPKeyring ( const std : : list < PGPIdType > & keys_to_remove , std : : string & backup_file , uint32_t & error_code )
{
// 1 - lock everything.
//
RsStackMutex mtx ( pgphandlerMtx ) ; // lock access to PGP memory structures.
RsStackFileLock flck ( _pgp_lock_filename ) ; // lock access to PGP directory.
error_code = PGP_KEYRING_REMOVAL_ERROR_NO_ERROR ;
for ( std : : list < PGPIdType > : : const_iterator it ( keys_to_remove . begin ( ) ) ; it ! = keys_to_remove . end ( ) ; + + it )
if ( locked_getSecretKey ( * it ) ! = NULL )
{
std : : cerr < < " (EE) PGPHandler:: can't remove key " < < ( * it ) . toStdString ( ) < < " since its shared by a secret key! Operation cancelled. " < < std : : endl ;
error_code = PGP_KEYRING_REMOVAL_ERROR_CANT_REMOVE_SECRET_KEYS ;
return false ;
}
// 2 - sync everything.
//
locked_syncPublicKeyring ( ) ;
// 3 - make a backup of the public keyring
//
char template_name [ _pubring_path . length ( ) + 8 ] ;
sprintf ( template_name , " %s.XXXXXX " , _pubring_path . c_str ( ) ) ;
if ( mktemp ( template_name ) = = NULL )
{
std : : cerr < < " PGPHandler::removeKeysFromPGPKeyring(): cannot create keyring backup file. Giving up. " < < std : : endl ;
error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_CREATE_BACKUP ;
return false ;
}
if ( ! ops_write_keyring_to_file ( _pubring , ops_false , template_name , ops_true ) )
{
std : : cerr < < " PGPHandler::removeKeysFromPGPKeyring(): cannot write keyring backup file. Giving up. " < < std : : endl ;
error_code = PGP_KEYRING_REMOVAL_ERROR_CANNOT_WRITE_BACKUP ;
return false ;
}
backup_file = std : : string ( template_name , _pubring_path . length ( ) + 7 ) ;
std : : cerr < < " Keyring was backed up to file " < < backup_file < < std : : endl ;
// Remove keys from the keyring, and update the keyring map.
//
for ( std : : list < PGPIdType > : : const_iterator it ( keys_to_remove . begin ( ) ) ; it ! = keys_to_remove . end ( ) ; + + it )
{
if ( locked_getSecretKey ( * it ) ! = NULL )
{
std : : cerr < < " (EE) PGPHandler:: can't remove key " < < ( * it ) . toStdString ( ) < < " since its shared by a secret key! " < < std : : endl ;
continue ;
}
std : : map < std : : string , PGPCertificateInfo > : : iterator res = _public_keyring_map . find ( ( * it ) . toStdString ( ) ) ;
if ( res = = _public_keyring_map . end ( ) )
{
std : : cerr < < " (EE) PGPHandler:: can't remove key " < < ( * it ) . toStdString ( ) < < " from keyring: key not found. " < < std : : endl ;
continue ;
}
2013-07-06 15:59:42 -04:00
if ( res - > second . _key_index > = ( unsigned int ) _pubring - > nkeys | | PGPIdType ( _pubring - > keys [ res - > second . _key_index ] . key_id ) ! = * it )
2013-05-31 15:16:04 -04:00
{
std : : cerr < < " (EE) PGPHandler:: can't remove key " < < ( * it ) . toStdString ( ) < < " . Inconsistency found. " < < std : : endl ;
error_code = PGP_KEYRING_REMOVAL_ERROR_DATA_INCONSISTENCY ;
return false ;
}
2013-05-29 17:32:02 -04:00
// Move the last key to the freed place. This deletes the key in place.
//
ops_keyring_remove_key ( _pubring , res - > second . _key_index ) ;
// Erase the info from the keyring map.
//
_public_keyring_map . erase ( res ) ;
2013-05-31 13:33:20 -04:00
// now update all indices back. This internal look is very costly, but it avoids deleting the wrong keys, since the keyring structure is
// changed by ops_keyring_remove_key and therefore indices don't point to the correct location anymore.
int i = 0 ;
const ops_keydata_t * keydata ;
while ( ( keydata = ops_keyring_get_key_by_index ( _pubring , i ) ) ! = NULL )
{
PGPCertificateInfo & cert ( _public_keyring_map [ PGPIdType ( keydata - > key_id ) . toStdString ( ) ] ) ;
cert . _key_index = i ;
+ + i ;
}
2013-05-29 17:32:02 -04:00
}
// Everything went well, sync back the keyring on disk
_pubring_changed = true ;
_trustdb_changed = true ;
locked_syncPublicKeyring ( ) ;
locked_syncTrustDatabase ( ) ;
return true ;
}
2012-06-29 15:38:19 -04:00