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-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-04-29 07:57:03 -04:00
# include <openpgpsdk/../../src/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.
2012-06-12 16:31:13 -04:00
# include "util/rsdir.h" // For rsicontrol.
2012-06-15 17:58:46 -04:00
# include "util/pgpkey.h" // For rsicontrol.
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 ;
// validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
// ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
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 ;
std : : string uid_hint = std : : string ( ( const char * ) cbinfo - > cryptinfo . keydata - > uids [ 0 ] . user_id ) ;
uid_hint + = " ( " + PGPIdType ( cbinfo - > cryptinfo . keydata - > key_id ) . toStdString ( ) + " ) " ;
passwd = PGPHandler : : passphraseCallback ( ) ( NULL , uid_hint . c_str ( ) , NULL , prev_was_bad ) ;
// if (rsicontrol->getNotify().askForPassword(uid_hint, prev_was_bad, passwd) == false)
// return OPS_RELEASE_MEMORY;
* ( 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-06-12 16:31:13 -04:00
_pubring_changed = false ;
_secring_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 ;
exit ( - 1 ) ;
}
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 ;
ftest = fopen ( pubring . c_str ( ) , " rb " ) ;
bool pubring_exist = ( ftest ! = NULL ) ;
if ( ftest ! = NULL )
fclose ( ftest ) ;
ftest = fopen ( secring . c_str ( ) , " rb " ) ;
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-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-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-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-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 ;
2012-04-09 13:03:47 -04:00
2012-04-22 07:36:34 -04:00
ops_fingerprint_t f ;
ops_fingerprint ( & f , & keydata - > key . pkey ) ;
cert . _fpr = PGPFingerprintType ( f . fingerprint ) ;
2012-06-14 16:13:31 -04:00
if ( keydata - > key . pkey . algorithm ! = OPS_PKA_RSA )
cert . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM ;
2012-05-13 15:04:13 -04:00
}
void PGPHandler : : validateAndUpdateSignatures ( PGPCertificateInfo & cert , const ops_keydata_t * keydata )
{
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
// Parse signers.
//
2012-05-13 15:04:13 -04:00
if ( result ! = NULL )
for ( size_t i = 0 ; i < result - > valid_count ; + + i )
cert . signers . insert ( PGPIdType ( result - > valid_sigs [ i ] . signer_id ) . toStdString ( ) ) ;
ops_validate_result_free ( result ) ;
2012-04-09 13:03:47 -04:00
}
2012-03-26 17:17:04 -04:00
PGPHandler : : ~ PGPHandler ( )
{
std : : cerr < < " Freeing PGPHandler. Deleting keyrings. " < < std : : endl ;
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-04-22 07:36:34 -04:00
std : : cerr < < " Printing details of all " < < std : : dec < < _public_keyring_map . size ( ) < < " keys: " < < std : : endl ;
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 ;
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 ;
}
const PGPCertificateInfo * PGPHandler : : getCertificateInfo ( const PGPIdType & id ) const
2012-03-27 16:48:21 -04:00
{
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 )
{
// 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 )
{
// check that the key is in the pubring as well
if ( ops_keyring_find_key_by_id ( _pubring , keydata - > key_id ) ! = NULL )
2012-06-14 16:13:31 -04:00
if ( keydata - > key . pkey . algorithm = = OPS_PKA_RSA )
ids . push_back ( PGPIdType ( keydata - > key_id ) ) ;
else
std : : cerr < < " Skipping keypair " < < PGPIdType ( keydata - > key_id ) . toStdString ( ) < < " , unsupported algorithm: " < < keydata - > key . pkey . algorithm < < std : : endl ;
2012-03-27 16:48:21 -04:00
}
return true ;
}
2012-04-08 10:52:01 -04:00
2012-03-27 16:48:21 -04:00
bool PGPHandler : : GeneratePGPCertificate ( const std : : string & name , const std : : string & email , const std : : string & passwd , PGPIdType & pgpId , std : : string & errString )
{
static const int KEY_NUMBITS = 2048 ;
ops_user_id_t uid ;
2012-04-01 12:43:23 -04:00
char * s = strdup ( ( name + " " + email + " (Generated by RetroShare) " ) . c_str ( ) ) ;
2012-03-27 16:48:21 -04:00
uid . user_id = ( unsigned char * ) s ;
2012-03-29 17:51:37 -04:00
unsigned long int e = 17 ; // 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-04-01 08:52:15 -04:00
// 1 - get a passphrase for encrypting.
2012-04-08 10:52:01 -04:00
std : : string passphrase = _passphrase_callback ( NULL , PGPIdType ( key - > key_id ) . toStdString ( ) . c_str ( ) , " Please enter passwd for encrypting your key : " , false ) ;
2012-03-27 16:48:21 -04:00
2012-04-01 08:52:15 -04:00
// 2 - save the private key encrypted to a temporary memory buffer
ops_create_info_t * cinfo = NULL ;
ops_memory_t * buf = NULL ;
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
ops_write_transferable_secret_key ( key , ( unsigned char * ) passphrase . c_str ( ) , passphrase . length ( ) , ops_false , cinfo ) ;
2012-04-01 12:43:23 -04:00
ops_keydata_free ( key ) ;
2012-04-01 08:52:15 -04:00
// 3 - read the file into a keyring
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
if ( ! ops_keyring_read_from_mem ( tmp_keyring , ops_false , buf ) )
{
std : : cerr < < " Cannot re-read key from memory!! " < < std : : endl ;
return false ;
}
ops_teardown_memory_write ( cinfo , buf ) ; // cleanup memory
// 4 - copy the private key to the private keyring
pgpId = PGPIdType ( tmp_keyring - > keys [ 0 ] . key_id ) ;
addNewKeyToOPSKeyring ( _secring , tmp_keyring - > keys [ 0 ] ) ;
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _secret_keyring_map [ pgpId . toStdString ( ) ] , & tmp_keyring - > keys [ 0 ] , _secring - > nkeys - 1 ) ;
2012-04-01 08:52:15 -04:00
std : : cerr < < " Added new secret key with id " < < pgpId . toStdString ( ) < < " to secret keyring. " < < std : : endl ;
2012-04-01 17:10:54 -04:00
// 5 - copy the private key to the public keyring
addNewKeyToOPSKeyring ( _pubring , tmp_keyring - > keys [ 0 ] ) ;
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _public_keyring_map [ pgpId . toStdString ( ) ] , & tmp_keyring - > keys [ 0 ] , _pubring - > nkeys - 1 ) ;
2012-04-01 17:10:54 -04:00
std : : cerr < < " Added new public key with id " < < pgpId . toStdString ( ) < < " to public keyring. " < < std : : endl ;
// 6 - clean
2012-03-29 17:51:37 -04:00
2012-04-01 08:52:15 -04:00
ops_keyring_free ( tmp_keyring ) ;
free ( tmp_keyring ) ;
2012-03-29 17:51:37 -04:00
2012-05-13 15:04:13 -04:00
// 7 - validate own signature and update certificate.
2012-05-14 16:01:00 -04:00
// validateAndUpdateSignatures(_public_keyring_map[ pgpId.toStdString() ],getPublicKey(pgpId)) ;
2012-05-13 15:04:13 -04:00
2012-06-12 16:31:13 -04:00
_pubring_changed = true ;
_secring_changed = true ;
2012-03-29 17:51:37 -04:00
return true ;
}
std : : string PGPHandler : : makeRadixEncodedPGPKey ( const ops_keydata_t * key )
{
2012-03-27 17:45:43 -04:00
ops_boolean_t armoured = ops_true ;
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-06-13 16:54:39 -04:00
if ( ops_write_transferable_public_key ( key , armoured , cinfo ) ! = ops_true )
return " ERROR: This key cannot be processed by RetroShare because \n DSA certificates are not yet handled. " ;
2012-03-29 17:51:37 -04:00
ops_writer_close ( cinfo ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
std : : string akey ( ( char * ) ops_memory_get_data ( buf ) , ops_memory_get_length ( buf ) ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
ops_teardown_memory_write ( cinfo , buf ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
return akey ;
}
2012-04-01 08:52:15 -04:00
const ops_keydata_t * PGPHandler : : getSecretKey ( const PGPIdType & id ) const
{
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
}
const ops_keydata_t * PGPHandler : : getPublicKey ( const PGPIdType & id ) const
{
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
2012-04-09 13:03:47 -04:00
return ops_keyring_get_key_by_index ( _pubring , res - > second . _key_index ) ;
2012-04-01 08:52:15 -04:00
}
2012-03-29 17:51:37 -04:00
std : : string PGPHandler : : SaveCertificateToString ( const PGPIdType & id , bool include_signatures )
{
2012-04-01 08:52:15 -04:00
const ops_keydata_t * key = getPublicKey ( id ) ;
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 " " ;
}
return makeRadixEncodedPGPKey ( key ) ;
2012-03-27 16:48:21 -04:00
}
2012-04-01 08:52:15 -04:00
void PGPHandler : : addNewKeyToOPSKeyring ( ops_keyring_t * kr , const ops_keydata_t & key )
{
kr - > keys = ( ops_keydata_t * ) realloc ( kr - > keys , ( kr - > nkeys + 1 ) * sizeof ( ops_keydata_t ) ) ;
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-06-15 17:58:46 -04:00
std : : cerr < < " Reading new key from string: " < < std : : endl ;
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-15 17:58:46 -04:00
std : : cerr < < " Key read correctly: " < < std : : endl ;
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 )
{
id = PGPIdType ( keydata - > key_id ) ;
2012-06-15 17:58:46 -04:00
std : : cerr < < " id: " < < id . toStdString ( ) < < std : : endl ;
// See if the key is already in the keyring
const ops_keydata_t * existing_key ;
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id . toStdString ( ) ) ;
if ( res = = _public_keyring_map . end ( ) | | ( existing_key = ops_keyring_get_key_by_index ( _pubring , res - > second . _key_index ) ) = = NULL )
{
std : : cerr < < " Key is new. Adding it to keyring " < < std : : endl ;
addNewKeyToOPSKeyring ( _pubring , * keydata ) ; // the key is new.
}
else
{
std : : cerr < < " Key exists. Merging signatures. " < < std : : endl ;
if ( mergeKeySignatures ( const_cast < ops_keydata_t * > ( existing_key ) , keydata ) )
_pubring_changed = true ;
}
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _public_keyring_map [ id . toStdString ( ) ] , keydata , _pubring - > nkeys - 1 ) ;
2012-05-13 15:04:13 -04:00
validateAndUpdateSignatures ( _public_keyring_map [ id . toStdString ( ) ] , keydata ) ;
2012-04-01 08:52:15 -04:00
}
2012-06-15 17:58:46 -04:00
std : : cerr < < " Added the key in the main public keyring. " < < std : : endl ;
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 ;
}
2012-06-12 16:31:13 -04:00
bool PGPHandler : : writePublicKeyring ( )
2012-04-08 10:52:01 -04:00
{
2012-06-12 16:31:13 -04:00
RsStackFileLock flck ( _pgp_lock_filename ) ; // locks access to pgp directory
_pubring_changed = false ;
return ops_write_keyring_to_file ( _pubring , ops_false , _pubring_path . c_str ( ) ) ;
}
bool PGPHandler : : writeSecretKeyring ( )
{
RsStackFileLock flck ( _pgp_lock_filename ) ; // locks access to pgp directory
_secring_changed = false ;
return ops_write_keyring_to_file ( _secring , ops_false , _secring_path . c_str ( ) ) ;
2012-05-01 14:45:24 -04:00
}
2012-04-08 10:52:01 -04:00
2012-05-01 14:45:24 -04:00
bool PGPHandler : : encryptTextToFile ( const PGPIdType & key_id , const std : : string & text , const std : : string & outfile )
{
2012-04-08 10:52:01 -04:00
ops_create_info_t * info ;
int fd = ops_setup_file_write ( & info , outfile . c_str ( ) , ops_true ) ;
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 ( fd < 0 )
{
2012-05-01 14:45:24 -04:00
std : : cerr < < " PGPHandler::encryptTextToFile(): ERROR: Cannot write to " < < outfile < < std : : endl ;
2012-04-08 10:52:01 -04:00
return false ;
}
ops_encrypt_stream ( info , public_key , NULL , ops_false , ops_true ) ;
ops_write ( text . c_str ( ) , text . length ( ) , info ) ;
ops_writer_close ( info ) ;
ops_create_info_delete ( info ) ;
return true ;
}
bool PGPHandler : : decryptTextFromFile ( const PGPIdType & key_id , std : : string & text , const std : : string & inputfile )
{
unsigned char * out_buf = NULL ;
std : : string buf ;
FILE * f = fopen ( inputfile . c_str ( ) , " rb " ) ;
2012-06-14 18:53:02 -04:00
if ( f = = NULL )
{
return false ;
}
2012-04-08 10:52:01 -04:00
char c ;
while ( ( c = getc ( f ) ) ! = EOF )
buf + = c ;
fclose ( f ) ;
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-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 ;
}
2012-04-01 08:52:15 -04:00
bool PGPHandler : : SignDataBin ( const PGPIdType & id , const void * data , const uint32_t len , unsigned char * sign , unsigned int * signlen )
{
// need to find the key and to decrypt it.
const ops_keydata_t * key = getSecretKey ( id ) ;
if ( ! key )
{
std : : cerr < < " Cannot sign: no secret key with id " < < id . toStdString ( ) < < std : : endl ;
return false ;
}
2012-04-08 10:52:01 -04:00
std : : string passphrase = _passphrase_callback ( NULL , PGPIdType ( key - > key_id ) . toStdString ( ) . 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.
2012-05-01 04:53:32 -04:00
ops_memory_t * memres = ops_sign_buf ( data , len , ( ops_sig_type_t ) 0x00 , secret_key , ops_false , ops_false ) ;
2012-04-01 08:52:15 -04:00
if ( ! memres )
return false ;
uint32_t tlen = std : : min ( * signlen , ( uint32_t ) ops_memory_get_length ( memres ) ) ;
memcpy ( sign , ops_memory_get_data ( memres ) , tlen ) ;
* signlen = tlen ;
2012-04-01 12:43:23 -04:00
ops_memory_release ( memres ) ;
free ( memres ) ;
ops_secret_key_free ( secret_key ) ;
free ( secret_key ) ;
2012-04-01 08:52:15 -04:00
return true ;
}
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-04-04 15:27:07 -04:00
const ops_keydata_t * key = getPublicKey ( id ) ;
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-06-06 16:31:19 -04:00
PGPIdType id = PGPIdType ( key_fingerprint . toByteArray ( ) + PGPFingerprintType : : SIZE_IN_BYTES - PGPIdType : : SIZE_IN_BYTES ) ;
2012-04-04 15:27:07 -04:00
const ops_keydata_t * key = getPublicKey ( id ) ;
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-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-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 )
{
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
{
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 ;
for ( int i = 0 ; i < p1 . length ; + + i )
{
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
std : : cerr < < " Merging signatures for key " < < PGPIdType ( dst - > key_id ) . toStdString ( ) < < std : : endl ;
std : : set < ops_packet_t > dst_packets ;
for ( int i = 0 ; i < dst - > npackets ; + + i ) dst_packets . insert ( dst - > packets [ i ] ) ;
std : : set < ops_packet_t > to_add ;
for ( int i = 0 ; i < src - > npackets ; + + i )
if ( dst_packets . find ( src - > packets [ i ] ) = = dst_packets . end ( ) )
{
uint8_t tag ;
uint32_t length ;
PGPKeyParser : : read_packetHeader ( src - > packets [ i ] . raw , tag , length ) ;
if ( tag = = PGPKeyParser : : PGP_PACKET_TAG_SIGNATURE )
to_add . insert ( src - > packets [ i ] ) ;
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 ;
}
for ( std : : set < ops_packet_t > : : const_iterator it ( to_add . begin ( ) ) ; it ! = to_add . end ( ) ; + + it )
{
std : : cerr < < " Adding packet with tag 0x " < < std : : hex < < ( int ) ( * it ) . raw [ 0 ] < < std : : dec < < std : : endl ;
ops_add_packet_to_keydata ( dst , & * it ) ;
}
return to_add . size ( ) > 0 ;
}
2012-06-20 17:59:04 -04:00
void PGPHandler : : privateTrustCertificate ( const PGPIdType & id , int trustlvl )
{
if ( trustlvl < 0 | | trustlvl > 6 )
{
std : : cerr < < " Invalid trust level " < < trustlvl < < " passed to privateTrustCertificate. " < < std : : endl ;
return ;
}
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 ;
return ;
}
if ( it - > second . _validLvl ! = trustlvl )
_trustdb_changed = true ;
it - > second . _validLvl = trustlvl ;
}
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.
uint32_t flags ; // not used yet, but who knows?
} ;
void PGPHandler : : locked_readPrivateTrustDatabase ( )
{
FILE * fdb = fopen ( _trustdb_path . c_str ( ) , " rb " ) ;
std : : cerr < < " PGPHandler: Reading private trust database. " < < std : : endl ;
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 ;
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 ;
}
it - > second . _validLvl = trustpacket . trust_level ;
}
fclose ( fdb ) ;
}
void PGPHandler : : locked_writePrivateTrustDatabase ( )
{
FILE * fdb = fopen ( ( _trustdb_path + " .tmp " ) . c_str ( ) , " wb " ) ;
std : : cerr < < " PGPHandler: Reading private trust database. " < < std : : endl ;
if ( fdb = = NULL )
{
std : : cerr < < " (EE) Can't open private trust database file " < < _trustdb_path < < " for write. Giving up! " < < std : : endl ;
return ;
}
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 ) ;
trustpacket . trust_level = it - > second . _validLvl ;
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 ) ;
return ;
}
}
fclose ( fdb ) ;
if ( ! RsDirUtil : : renameFile ( _trustdb_path + " .tmp " , _trustdb_path ) )
std : : cerr < < " (EE) Cannot move temp file " < < _trustdb_path + " .tmp " < < " . Bad write permissions? " < < std : : endl ;
}
2012-06-15 17:58:46 -04:00