mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-31 11:41:32 +01:00
*** empty log message ***
This commit is contained in:
parent
ed36092588
commit
922e57dd57
@ -26,6 +26,7 @@
|
||||
* key "abcdefghijklmnopqrstuvwxyz";
|
||||
* plain "BLOWFISH"
|
||||
* cipher 32 4E D0 FE F4 13 A2 03
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -385,6 +386,9 @@ selftest()
|
||||
BLOWFISH_context c;
|
||||
byte plain[] = "BLOWFISH";
|
||||
byte buffer[8];
|
||||
byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||
byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 };
|
||||
byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 };
|
||||
|
||||
blowfish_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
|
||||
encrypt_block( &c, buffer, plain );
|
||||
@ -393,6 +397,14 @@ selftest()
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain, 8 ) )
|
||||
log_bug("blowfish failed\n");
|
||||
|
||||
blowfish_setkey( &c, key3, 8 );
|
||||
encrypt_block( &c, buffer, plain3 );
|
||||
if( memcmp( buffer, cipher3, 8 ) )
|
||||
log_error("wrong blowfish encryption (3)\n");
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain3, 8 ) )
|
||||
log_bug("blowfish failed (3)\n");
|
||||
}
|
||||
|
||||
|
||||
|
11
doc/DETAILS
11
doc/DETAILS
@ -36,7 +36,7 @@ Record type 1:
|
||||
against the pubring)
|
||||
1 u32 Local-Id-Counter. Used to keep track of Local-IDs.
|
||||
32 bits are enough numbers for all practial purposes; if this
|
||||
counter rolls over (due to deleted keyblock,an d new ones),
|
||||
counter rolls over (due to deleted keyblock and new ones),
|
||||
the software should reassign new Local-Ids to the whole
|
||||
database (not expected to ever occur).
|
||||
1 byte marginals needed
|
||||
@ -49,6 +49,7 @@ Record type 1:
|
||||
Record type 2:
|
||||
--------------
|
||||
Informations about a public key certificate.
|
||||
These are static values which are never changed without user interaction.
|
||||
|
||||
1 byte value 2
|
||||
1 byte reserved
|
||||
@ -57,7 +58,7 @@ Record type 2:
|
||||
and usefull if we have duplicate keyids
|
||||
It is not defined, how an implementaion selects such
|
||||
a Local-Id, but it may use the local-ID counter from
|
||||
record type 1
|
||||
record type 1, or simply use the offset of Record type 2
|
||||
8 bytes keyid (of the primary key)
|
||||
1 byte pubkey algorithm
|
||||
1 byte reserved
|
||||
@ -67,9 +68,9 @@ Record type 2:
|
||||
0 = undefined (not yet initialized)
|
||||
1 = unknown owner (could not initialize it)
|
||||
2 = do not trust this owner
|
||||
3 = usually trust this owner
|
||||
4 = always trust this owner
|
||||
5 = ultimately trust this owner. This can only be set if
|
||||
4 = usually trust this owner
|
||||
5 = always trust this owner
|
||||
7 = ultimately trust this owner. This can only be set if
|
||||
we have control over the secret key too.
|
||||
Bit 3: set if key is revoked; do not use it.
|
||||
Bit 7-4: reserved
|
||||
|
@ -159,7 +159,7 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
{
|
||||
IOBUF inp = NULL, out = NULL;
|
||||
PACKET pkt;
|
||||
PKT_plaintext *pt;
|
||||
PKT_plaintext *pt = NULL;
|
||||
int rc = 0;
|
||||
u32 filesize;
|
||||
cipher_filter_context_t cfx;
|
||||
@ -244,7 +244,8 @@ encode_crypt( const char *filename, STRLIST remusr )
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
iobuf_close(out); /* fixme: check returncode */
|
||||
pt->buf = NULL;
|
||||
if( pt )
|
||||
pt->buf = NULL;
|
||||
free_packet(&pkt);
|
||||
m_free(cfx.dek);
|
||||
release_pkc_list( pkc_list );
|
||||
|
@ -57,18 +57,24 @@ free_seckey_enc( PKT_signature *enc )
|
||||
}
|
||||
|
||||
void
|
||||
free_public_cert( PKT_public_cert *cert )
|
||||
release_public_cert_parts( PKT_public_cert *cert )
|
||||
{
|
||||
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
mpi_free( cert->d.elg.p );
|
||||
mpi_free( cert->d.elg.g );
|
||||
mpi_free( cert->d.elg.y );
|
||||
mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL;
|
||||
mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL;
|
||||
mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL;
|
||||
}
|
||||
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_free( cert->d.rsa.rsa_n );
|
||||
mpi_free( cert->d.rsa.rsa_e );
|
||||
mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL;
|
||||
}
|
||||
md_close( cert->mfx.md );
|
||||
md_close( cert->mfx.md ); cert->mfx.md = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
free_public_cert( PKT_public_cert *cert )
|
||||
{
|
||||
release_public_cert_parts( cert );
|
||||
m_free(cert);
|
||||
}
|
||||
|
||||
@ -92,22 +98,28 @@ copy_public_cert( PKT_public_cert *d, PKT_public_cert *s )
|
||||
}
|
||||
|
||||
void
|
||||
free_secret_cert( PKT_secret_cert *cert )
|
||||
release_secret_cert_parts( PKT_secret_cert *cert )
|
||||
{
|
||||
if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
mpi_free( cert->d.elg.p );
|
||||
mpi_free( cert->d.elg.g );
|
||||
mpi_free( cert->d.elg.y );
|
||||
mpi_free( cert->d.elg.x );
|
||||
mpi_free( cert->d.elg.p ); cert->d.elg.p = NULL;
|
||||
mpi_free( cert->d.elg.g ); cert->d.elg.g = NULL;
|
||||
mpi_free( cert->d.elg.y ); cert->d.elg.y = NULL;
|
||||
mpi_free( cert->d.elg.x ); cert->d.elg.x = NULL;
|
||||
}
|
||||
else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
mpi_free( cert->d.rsa.rsa_n );
|
||||
mpi_free( cert->d.rsa.rsa_e );
|
||||
mpi_free( cert->d.rsa.rsa_d );
|
||||
mpi_free( cert->d.rsa.rsa_p );
|
||||
mpi_free( cert->d.rsa.rsa_q );
|
||||
mpi_free( cert->d.rsa.rsa_u );
|
||||
mpi_free( cert->d.rsa.rsa_n ); cert->d.rsa.rsa_n = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_e ); cert->d.rsa.rsa_e = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_d ); cert->d.rsa.rsa_d = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_p ); cert->d.rsa.rsa_p = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_q ); cert->d.rsa.rsa_q = NULL;
|
||||
mpi_free( cert->d.rsa.rsa_u ); cert->d.rsa.rsa_u = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_secret_cert( PKT_secret_cert *cert )
|
||||
{
|
||||
release_secret_cert_parts( cert );
|
||||
m_free(cert);
|
||||
}
|
||||
|
||||
@ -240,4 +252,34 @@ free_packet( PACKET *pkt )
|
||||
pkt->pkt.generic = NULL;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Returns 0 if they match.
|
||||
*/
|
||||
int
|
||||
cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc )
|
||||
{
|
||||
if( pkc->timestamp != skc->timestamp )
|
||||
return -1;
|
||||
if( pkc->valid_days != skc->valid_days )
|
||||
return -1;
|
||||
if( pkc->pubkey_algo != skc->pubkey_algo )
|
||||
return -1;
|
||||
|
||||
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
|
||||
if( mpi_cmp( pkc->d.elg.p , skc->d.elg.p ) )
|
||||
return -1;
|
||||
if( mpi_cmp( pkc->d.elg.g , skc->d.elg.g ) )
|
||||
return -1;
|
||||
if( mpi_cmp( pkc->d.elg.y , skc->d.elg.y ) )
|
||||
return -1;
|
||||
}
|
||||
else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
|
||||
if( mpi_cmp( pkc->d.rsa.rsa_n , skc->d.rsa.rsa_n ) )
|
||||
return -1;
|
||||
if( mpi_cmp( pkc->d.rsa.rsa_e , skc->d.rsa.rsa_e ) )
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
29
g10/g10.c
29
g10/g10.c
@ -424,17 +424,36 @@ main( int argc, char **argv )
|
||||
break;
|
||||
|
||||
case aSign: /* sign the given file */
|
||||
if( argc > 1 )
|
||||
usage(1);
|
||||
if( (rc = sign_file(fname, detached_sig, locusr, 0, NULL)) )
|
||||
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
|
||||
sl = NULL;
|
||||
if( detached_sig ) { /* sign all files */
|
||||
for( ; argc; argc--, argv++ )
|
||||
add_to_strlist( &sl, *argv );
|
||||
}
|
||||
else {
|
||||
if( argc > 1 )
|
||||
usage(1);
|
||||
if( argc ) {
|
||||
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
||||
strcpy(sl->d, fname);
|
||||
}
|
||||
}
|
||||
if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
|
||||
log_error("sign_file: %s\n", g10_errstr(rc) );
|
||||
free_strlist(sl);
|
||||
break;
|
||||
|
||||
case aSignEncr: /* sign and encrypt the given file */
|
||||
if( argc > 1 )
|
||||
usage(1);
|
||||
if( (rc = sign_file(fname, detached_sig, locusr, 1, remusr)) )
|
||||
if( argc ) {
|
||||
sl = m_alloc_clear( sizeof *sl + strlen(fname));
|
||||
strcpy(sl->d, fname);
|
||||
}
|
||||
else
|
||||
sl = NULL;
|
||||
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
|
||||
log_error("sign_file('%s'): %s\n", fname_print, g10_errstr(rc) );
|
||||
free_strlist(sl);
|
||||
break;
|
||||
|
||||
|
||||
|
73
g10/getkey.c
73
g10/getkey.c
@ -51,6 +51,13 @@ typedef struct pkc_cache_entry {
|
||||
PKT_public_cert *pkc;
|
||||
} *pkc_cache_entry_t;
|
||||
|
||||
typedef struct enum_seckey_context {
|
||||
int eof;
|
||||
STRLIST sl;
|
||||
IOBUF iobuf;
|
||||
} enum_seckey_context_t;
|
||||
|
||||
|
||||
static STRLIST keyrings;
|
||||
static STRLIST secret_keyrings;
|
||||
|
||||
@ -351,6 +358,9 @@ get_seckey_byname( PKT_secret_cert *skc, const char *name, int unprotect )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* scan the keyring and look for either the keyid or the name.
|
||||
*/
|
||||
@ -584,6 +594,69 @@ scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Enumerate all secret keys. Caller must use these procedure:
|
||||
* 1) create a void pointer and initialize it to NULL
|
||||
* 2) pass this void pointer by reference to this function
|
||||
* and provide space for the secret key (pass a buffer for skc)
|
||||
* 3) call this function as long as it does not return -1
|
||||
* to indicate EOF.
|
||||
* 4) Always call this function a last time with SKC set to NULL,
|
||||
* so that can free it's context.
|
||||
*
|
||||
* Return
|
||||
*/
|
||||
int
|
||||
enum_secret_keys( void **context, PKT_secret_cert *skc )
|
||||
{
|
||||
int rc=0;
|
||||
PACKET pkt;
|
||||
int save_mode;
|
||||
enum_seckey_context_t *c = *context;
|
||||
|
||||
if( !c ) { /* make a new context */
|
||||
c = m_alloc_clear( sizeof *c );
|
||||
*context = c;
|
||||
c->sl = secret_keyrings;
|
||||
}
|
||||
|
||||
if( !skc ) { /* free the context */
|
||||
m_free( c );
|
||||
*context = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( c->eof )
|
||||
return -1;
|
||||
|
||||
for( ; c->sl; c->sl = c->sl->next ) {
|
||||
if( !c->iobuf ) {
|
||||
if( !(c->iobuf = iobuf_open( c->sl->d ) ) ) {
|
||||
log_error("enum_secret_keys: can't open '%s'\n", c->sl->d );
|
||||
continue; /* try next file */
|
||||
}
|
||||
}
|
||||
|
||||
save_mode = set_packet_list_mode(0);
|
||||
init_packet(&pkt);
|
||||
while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
|
||||
if( rc )
|
||||
; /* e.g. unknown packet */
|
||||
else if( pkt.pkttype == PKT_SECRET_CERT ) {
|
||||
copy_secret_cert( skc, pkt.pkt.secret_cert );
|
||||
set_packet_list_mode(save_mode);
|
||||
return 0; /* found */
|
||||
}
|
||||
free_packet(&pkt);
|
||||
}
|
||||
set_packet_list_mode(save_mode);
|
||||
iobuf_close(c->iobuf); c->iobuf = NULL;
|
||||
}
|
||||
c->eof = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return a string with a printable representation of the user_id.
|
||||
* this string must be freed by m_free.
|
||||
|
@ -97,6 +97,7 @@ int get_pubkey( PKT_public_cert *pkc, u32 *keyid );
|
||||
int get_pubkey_byname( PKT_public_cert *pkc, const char *name );
|
||||
int get_seckey( PKT_secret_cert *skc, u32 *keyid );
|
||||
int get_seckey_byname( PKT_secret_cert *skc, const char *name, int unlock );
|
||||
int enum_secret_keys( void **context, PKT_secret_cert *skc );
|
||||
char*get_user_id_string( u32 *keyid );
|
||||
char*get_user_id( u32 *keyid, size_t *rn );
|
||||
|
||||
|
@ -41,8 +41,8 @@ int encrypt_filter( void *opaque, int control,
|
||||
|
||||
|
||||
/*-- sign.c --*/
|
||||
int sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
int encrypt, STRLIST remusr );
|
||||
int sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
||||
int encrypt, STRLIST remusr, const char *outfile );
|
||||
int sign_key( const char *username, STRLIST locusr );
|
||||
int edit_keysigs( const char *username );
|
||||
int change_passphrase( const char *username );
|
||||
|
@ -58,11 +58,13 @@ struct {
|
||||
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
|
||||
#define DBG_CACHE_VALUE 64 /* debug the cacheing */
|
||||
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
|
||||
#define DBG_TRUST_VALUE 256 /* debug the trustdb */
|
||||
|
||||
|
||||
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
|
||||
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
|
||||
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
||||
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
|
||||
|
||||
|
||||
#endif /*G10_OPTIONS_H*/
|
||||
|
@ -98,6 +98,7 @@ typedef struct {
|
||||
u16 valid_days; /* valid for this number of days */
|
||||
byte pubkey_algo; /* algorithm used for public key scheme */
|
||||
md_filter_context_t mfx;
|
||||
u32 local_id; /* internal use, valid if > 0 */
|
||||
union {
|
||||
struct {
|
||||
MPI p; /* prime */
|
||||
@ -225,13 +226,16 @@ void hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc );
|
||||
/*-- free-packet.c --*/
|
||||
void free_pubkey_enc( PKT_pubkey_enc *enc );
|
||||
void free_seckey_enc( PKT_signature *enc );
|
||||
void release_public_cert_parts( PKT_public_cert *cert );
|
||||
void free_public_cert( PKT_public_cert *cert );
|
||||
void release_secret_cert_parts( PKT_secret_cert *cert );
|
||||
void free_secret_cert( PKT_secret_cert *cert );
|
||||
void free_user_id( PKT_user_id *uid );
|
||||
void free_comment( PKT_comment *rem );
|
||||
void free_packet( PACKET *pkt );
|
||||
PKT_public_cert *copy_public_cert( PKT_public_cert *d, PKT_public_cert *s );
|
||||
PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s );
|
||||
int cmp_public_secret_cert( PKT_public_cert *pkc, PKT_secret_cert *skc );
|
||||
|
||||
|
||||
/*-- sig-check.c --*/
|
||||
|
@ -41,6 +41,25 @@
|
||||
static int
|
||||
do_we_trust( PKT_public_cert *pkc, int trustlevel )
|
||||
{
|
||||
int rc;
|
||||
|
||||
if( trustlevel & TRUST_NO_PUBKEY ) {
|
||||
/* No pubkey in trustDB: Insert and check again */
|
||||
rc = insert_trust_record( pkc );
|
||||
if( rc ) {
|
||||
log_error("failed to insert it into the trustdb: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return 0; /* no */
|
||||
}
|
||||
rc = check_pkc_trust( pkc, &trustlevel );
|
||||
if( rc )
|
||||
log_fatal("trust check after insert failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
if( trustlevel & TRUST_NO_PUBKEY )
|
||||
log_bug(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Eventuell fragen falls der trustlevel nicht ausreichend ist */
|
||||
|
||||
|
||||
@ -90,6 +109,7 @@ build_pkc_list( STRLIST remusr, PKC_LIST *ret_pkc_list )
|
||||
remusr->d, g10_errstr(rc) );
|
||||
}
|
||||
else if( do_we_trust( pkc, trustlevel ) ) {
|
||||
/* note: do_we_trust may have changed the trustlevel */
|
||||
PKC_LIST r;
|
||||
|
||||
r = m_alloc( sizeof *r );
|
||||
|
95
g10/sign.c
95
g10/sign.c
@ -64,17 +64,22 @@ complete_sig( PKT_signature *sig, PKT_secret_cert *skc, MD_HANDLE md )
|
||||
|
||||
|
||||
/****************
|
||||
* Sign the file with name FILENAME. If DETACHED has the value true,
|
||||
* make a detached signature. If FILENAME is NULL read from stdin
|
||||
* Sign the files whose names are in FILENAME.
|
||||
* If DETACHED has the value true,
|
||||
* make a detached signature. If FILENAMES->d is NULL read from stdin
|
||||
* and ignore the detached mode. Sign the file with all secret keys
|
||||
* which can be taken from LOCUSR, if this is NULL, use the default one
|
||||
* If ENCRYPT is true, use REMUSER (or ask if it is NULL) to encrypt the
|
||||
* signed data for these users.
|
||||
* If OUTFILE is not NULL; this file is used for output and the function
|
||||
* does not ask for overwrite permission; output is then always
|
||||
* uncompressed, non-armored and in binary mode.
|
||||
*/
|
||||
int
|
||||
sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
int encrypt, STRLIST remusr )
|
||||
sign_file( STRLIST filenames, int detached, STRLIST locusr,
|
||||
int encrypt, STRLIST remusr, const char *outfile )
|
||||
{
|
||||
const char *fname;
|
||||
armor_filter_context_t afx;
|
||||
compress_filter_context_t zfx;
|
||||
md_filter_context_t mfx;
|
||||
@ -88,6 +93,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
PKC_LIST pkc_list = NULL;
|
||||
SKC_LIST skc_list = NULL;
|
||||
SKC_LIST skc_rover = NULL;
|
||||
int multifile = 0;
|
||||
|
||||
memset( &afx, 0, sizeof afx);
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
@ -96,6 +102,16 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
memset( &efx, 0, sizeof efx);
|
||||
init_packet( &pkt );
|
||||
|
||||
if( filenames ) {
|
||||
fname = filenames->d;
|
||||
multifile = !!filenames->next;
|
||||
}
|
||||
else
|
||||
fname = NULL;
|
||||
|
||||
if( fname && filenames->next && (!detached || encrypt) )
|
||||
log_bug("multiple files can only be detached signed");
|
||||
|
||||
if( (rc=build_skc_list( locusr, &skc_list, 1 )) )
|
||||
goto leave;
|
||||
if( encrypt ) {
|
||||
@ -104,28 +120,40 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
}
|
||||
|
||||
/* prepare iobufs */
|
||||
if( !(inp = iobuf_open(filename)) ) {
|
||||
log_error("can't open %s: %s\n", filename? filename: "[stdin]",
|
||||
if( multifile ) /* have list of filenames */
|
||||
inp = NULL; /* we do it later */
|
||||
else if( !(inp = iobuf_open(fname)) ) {
|
||||
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
|
||||
strerror(errno) );
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( !(out = open_outfile( filename, opt.armor? 1: detached? 2:0 )) ) {
|
||||
if( outfile ) {
|
||||
if( !(out = iobuf_create( outfile )) ) {
|
||||
log_error("can't create %s: %s\n", outfile, strerror(errno) );
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
else if( opt.verbose )
|
||||
log_info("writing to '%s'\n", outfile );
|
||||
}
|
||||
else if( !(out = open_outfile( fname, opt.armor? 1: detached? 2:0 )) ) {
|
||||
rc = G10ERR_CREATE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* prepare to calculate the MD over the input */
|
||||
if( opt.textmode && opt.armor )
|
||||
if( opt.textmode && opt.armor && !outfile )
|
||||
iobuf_push_filter( inp, text_filter, &tfx );
|
||||
mfx.md = md_open(DIGEST_ALGO_RMD160, 0);
|
||||
iobuf_push_filter( inp, md_filter, &mfx );
|
||||
if( !multifile )
|
||||
iobuf_push_filter( inp, md_filter, &mfx );
|
||||
|
||||
if( opt.armor )
|
||||
if( opt.armor && !outfile )
|
||||
iobuf_push_filter( out, armor_filter, &afx );
|
||||
write_comment( out, "#Created by G10 pre-release " VERSION );
|
||||
if( opt.compress )
|
||||
if( opt.compress && !outfile )
|
||||
iobuf_push_filter( out, compress_filter, &zfx );
|
||||
|
||||
if( encrypt ) {
|
||||
@ -141,7 +169,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
|
||||
skc = skc_rover->skc;
|
||||
ops = m_alloc_clear( sizeof *ops );
|
||||
ops->sig_class = opt.textmode? 0x01 : 0x00;
|
||||
ops->sig_class = opt.textmode && !outfile ? 0x01 : 0x00;
|
||||
ops->digest_algo = DIGEST_ALGO_RMD160;
|
||||
ops->pubkey_algo = skc->pubkey_algo;
|
||||
keyid_from_skc( skc, ops->keyid );
|
||||
@ -161,17 +189,40 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
|
||||
/* setup the inner packet */
|
||||
if( detached ) {
|
||||
/* read, so that the filter can calculate the digest */
|
||||
while( iobuf_get(inp) != -1 )
|
||||
;
|
||||
if( multifile ) {
|
||||
STRLIST sl = filenames;
|
||||
|
||||
if( opt.verbose )
|
||||
log_info("signing:" );
|
||||
for(; sl; sl = sl->next ) {
|
||||
if( !(inp = iobuf_open(sl->d)) ) {
|
||||
log_error("can't open %s: %s\n", sl->d, strerror(errno) );
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
if( opt.verbose )
|
||||
fprintf(stderr, " '%s'", sl->d );
|
||||
iobuf_push_filter( inp, md_filter, &mfx );
|
||||
while( iobuf_get(inp) != -1 )
|
||||
;
|
||||
iobuf_close(inp); inp = NULL;
|
||||
}
|
||||
if( opt.verbose )
|
||||
putc( '\n', stderr );
|
||||
}
|
||||
else {
|
||||
/* read, so that the filter can calculate the digest */
|
||||
while( iobuf_get(inp) != -1 )
|
||||
;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( filename ) {
|
||||
pt = m_alloc( sizeof *pt + strlen(filename) - 1 );
|
||||
pt->namelen = strlen(filename);
|
||||
memcpy(pt->name, filename, pt->namelen );
|
||||
if( fname ) {
|
||||
pt = m_alloc( sizeof *pt + strlen(fname) - 1 );
|
||||
pt->namelen = strlen(fname);
|
||||
memcpy(pt->name, fname, pt->namelen );
|
||||
if( !(filesize = iobuf_get_filelength(inp)) )
|
||||
log_info("warning: '%s' is an empty file\n", filename );
|
||||
log_info("warning: '%s' is an empty file\n", fname );
|
||||
}
|
||||
else { /* no filename */
|
||||
pt = m_alloc( sizeof *pt - 1 );
|
||||
@ -179,7 +230,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
filesize = 0; /* stdin */
|
||||
}
|
||||
pt->timestamp = make_timestamp();
|
||||
pt->mode = opt.textmode? 't':'b';
|
||||
pt->mode = opt.textmode && !outfile ? 't':'b';
|
||||
pt->len = filesize;
|
||||
pt->buf = inp;
|
||||
pkt.pkttype = PKT_PLAINTEXT;
|
||||
@ -203,7 +254,7 @@ sign_file( const char *filename, int detached, STRLIST locusr,
|
||||
sig = m_alloc_clear( sizeof *sig );
|
||||
sig->pubkey_algo = skc->pubkey_algo;
|
||||
sig->timestamp = make_timestamp();
|
||||
sig->sig_class = opt.textmode? 0x01 : 0x00;
|
||||
sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00;
|
||||
|
||||
md = md_copy( mfx.md );
|
||||
md_putc( md, sig->sig_class );
|
||||
|
588
g10/trustdb.c
588
g10/trustdb.c
@ -25,6 +25,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "errors.h"
|
||||
#include "iobuf.h"
|
||||
@ -41,7 +42,6 @@ struct trust_record {
|
||||
byte rectype;
|
||||
byte reserved;
|
||||
union {
|
||||
byte raw[TRUST_RECORD_LEN-2];
|
||||
struct { /* version record: */
|
||||
byte magic[2];
|
||||
byte version; /* should be 1 */
|
||||
@ -76,10 +76,32 @@ struct trust_record {
|
||||
} cache;
|
||||
} r;
|
||||
};
|
||||
typedef struct trust_record TRUSTREC;
|
||||
|
||||
|
||||
static void create_db( const char *fname );
|
||||
static void open_db(void);
|
||||
static int read_record( u32 recnum, TRUSTREC *rec );
|
||||
static u32 new_local_id(void);
|
||||
|
||||
static char *db_name;
|
||||
static int db_fd = -1;
|
||||
static int no_io_dbg = 0;
|
||||
|
||||
#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
|
||||
(*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
|
||||
#define buftou16( p ) ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
|
||||
#define u32tobuf( p, a ) do { \
|
||||
((byte*)p)[0] = a >> 24; \
|
||||
((byte*)p)[1] = a >> 16; \
|
||||
((byte*)p)[2] = a >> 8; \
|
||||
((byte*)p)[3] = a ; \
|
||||
} while(0)
|
||||
#define u16tobuf( p, a ) do { \
|
||||
((byte*)p)[0] = a >> 8; \
|
||||
((byte*)p)[1] = a ; \
|
||||
} while(0)
|
||||
|
||||
|
||||
/**************************************************
|
||||
************** read and write helpers ************
|
||||
@ -147,7 +169,7 @@ create_db( const char *fname )
|
||||
fwrite_32( fp, make_timestamp() ); /* created */
|
||||
fwrite_32( fp, 0 ); /* not yet modified */
|
||||
fwrite_32( fp, 0 ); /* not yet validated*/
|
||||
fwrite_32( fp, 0 ); /* local-id-counter */
|
||||
fwrite_32( fp, 0 ); /* local-id-counter (not used) */
|
||||
fwrite_8( fp, 3 ); /* marginals needed */
|
||||
fwrite_8( fp, 1 ); /* completes needed */
|
||||
fwrite_8( fp, 4 ); /* max_cet_depth */
|
||||
@ -155,14 +177,255 @@ create_db( const char *fname )
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void
|
||||
open_db()
|
||||
{
|
||||
TRUSTREC rec;
|
||||
assert( db_fd == -1 );
|
||||
|
||||
db_fd = open( db_name, O_RDWR );
|
||||
if( db_fd == -1 )
|
||||
log_fatal("can't open %s: %s\n", db_name, strerror(errno) );
|
||||
if( read_record( 0, &rec ) )
|
||||
log_fatal("TrustDB %s is invalid\n", db_name );
|
||||
/* fixme: check ->locked and other stuff */
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* read the record with number recnum
|
||||
* returns: -1 on error, 0 on success
|
||||
*/
|
||||
static int
|
||||
read_record( u32 recnum, TRUSTREC *rec )
|
||||
{
|
||||
byte buf[TRUST_RECORD_LEN], *p;
|
||||
int rc = 0;
|
||||
int n;
|
||||
|
||||
if( db_fd == -1 )
|
||||
open_db();
|
||||
if( DBG_TRUST && !no_io_dbg )
|
||||
log_debug("trustdb: read_record(%lu)\n", (ulong)recnum);
|
||||
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
|
||||
log_error("trustdb: lseek failed: %s\n", strerror(errno) );
|
||||
return G10ERR_READ_FILE;
|
||||
}
|
||||
n = read( db_fd, buf, TRUST_RECORD_LEN);
|
||||
if( !n ) {
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: no record at %lu\n", (ulong)recnum );
|
||||
return -1; /* eof */
|
||||
}
|
||||
else if( n != TRUST_RECORD_LEN ) {
|
||||
log_error("trustdb: read failed (n=%d): %s\n", n, strerror(errno) );
|
||||
return G10ERR_READ_FILE;
|
||||
}
|
||||
p = buf;
|
||||
rec->rectype = *p++;
|
||||
rec->reserved = *p++;
|
||||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
break;
|
||||
case 1: /* version record */
|
||||
rec->r.version.magic[0] = *p++;
|
||||
rec->r.version.magic[1] = *p++;
|
||||
rec->r.version.version = *p++;
|
||||
memcpy( rec->r.version.reserved, p, 3); p += 3;
|
||||
rec->r.version.locked = buftou32(p); p += 4;
|
||||
rec->r.version.created = buftou32(p); p += 4;
|
||||
rec->r.version.modified = buftou32(p); p += 4;
|
||||
rec->r.version.validated= buftou32(p); p += 4;
|
||||
rec->r.version.local_id_counter = buftou32(p); p += 4;
|
||||
rec->r.version.marginals_needed = *p++;
|
||||
rec->r.version.completes_needed = *p++;
|
||||
rec->r.version.max_cert_depth = *p++;
|
||||
if( recnum ) {
|
||||
log_error("%s: version record with recnum %lu\n",
|
||||
db_name, (ulong)recnum );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
if( rec->reserved != 'g' || rec->r.version.magic[0] != '1'
|
||||
|| rec->r.version.magic[1] != '0' ) {
|
||||
log_error("%s: not a trustdb file\n", db_name );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
if( rec->r.version.version != 1 ) {
|
||||
log_error("%s: invalid file version %d\n",
|
||||
db_name, rec->r.version.version );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
rec->r.pubkey.local_id = buftou32(p); p += 4;
|
||||
rec->r.pubkey.keyid[0] = buftou32(p); p += 4;
|
||||
rec->r.pubkey.keyid[1] = buftou32(p); p += 4;
|
||||
rec->r.pubkey.algo = *p++;
|
||||
rec->r.pubkey.reserved = *p++;
|
||||
memcpy( rec->r.pubkey.fingerprint, p, 20); p += 20;
|
||||
rec->r.pubkey.ownertrust = *p++;
|
||||
if( rec->r.pubkey.local_id != recnum ) {
|
||||
log_error("%s: pubkey local_id != recnum (%lu,%lu)\n",
|
||||
db_name,
|
||||
(ulong)rec->r.pubkey.local_id,
|
||||
(ulong)recnum );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
rec->r.cache.local_id = buftou32(p); p += 4;
|
||||
rec->r.cache.keyid[0] = buftou32(p); p += 4;
|
||||
rec->r.cache.keyid[1] = buftou32(p); p += 4;
|
||||
rec->r.cache.valid = *p++;
|
||||
rec->r.cache.reserved = *p++;
|
||||
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
|
||||
rec->r.cache.n_untrusted = *p++;
|
||||
rec->r.cache.n_marginal = *p++;
|
||||
rec->r.cache.n_fully = *p++;
|
||||
rec->r.cache.trustlevel = *p++;
|
||||
break;
|
||||
default:
|
||||
log_error("%s: invalid record type %d at recnum %lu\n",
|
||||
db_name, rec->rectype, (ulong)recnum );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Write the record at RECNUM
|
||||
*/
|
||||
static int
|
||||
write_record( u32 recnum, TRUSTREC *rec )
|
||||
{
|
||||
byte buf[TRUST_RECORD_LEN], *p;
|
||||
int rc = 0;
|
||||
int n;
|
||||
|
||||
if( db_fd == -1 )
|
||||
open_db();
|
||||
|
||||
if( DBG_TRUST && !no_io_dbg )
|
||||
log_debug("trustdb: write_record(%lu)\n", (ulong)recnum);
|
||||
memset(buf, 0, TRUST_RECORD_LEN);
|
||||
p = buf;
|
||||
*p++ = rec->rectype;
|
||||
*p++ = rec->reserved;
|
||||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
break;
|
||||
case 1: /* version record */
|
||||
log_bug(NULL);
|
||||
break;
|
||||
case 2:
|
||||
u32tobuf(p, rec->r.pubkey.local_id); p += 4;
|
||||
u32tobuf(p, rec->r.pubkey.keyid[0]); p += 4;
|
||||
u32tobuf(p, rec->r.pubkey.keyid[1]); p += 4;
|
||||
*p++ = rec->r.pubkey.algo;
|
||||
*p++ = rec->r.pubkey.reserved;
|
||||
memcpy( p, rec->r.pubkey.fingerprint, 20); p += 20;
|
||||
*p++ = rec->r.pubkey.ownertrust;
|
||||
assert( rec->r.pubkey.local_id == recnum );
|
||||
break;
|
||||
case 3:
|
||||
u32tobuf(p, rec->r.cache.local_id); p += 4;
|
||||
u32tobuf(p, rec->r.cache.keyid[0]); p += 4;
|
||||
u32tobuf(p, rec->r.cache.keyid[1]); p += 4;
|
||||
*p++ = rec->r.cache.valid;
|
||||
*p++ = rec->r.cache.reserved;
|
||||
memcpy(p, rec->r.cache.blockhash, 20); p += 20;
|
||||
*p++ = rec->r.cache.n_untrusted;
|
||||
*p++ = rec->r.cache.n_marginal;
|
||||
*p++ = rec->r.cache.n_fully;
|
||||
*p++ = rec->r.cache.trustlevel;
|
||||
break;
|
||||
default:
|
||||
log_bug(NULL);
|
||||
}
|
||||
|
||||
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
|
||||
log_error("trustdb: lseek failed: %s\n", strerror(errno) );
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
n = write( db_fd, buf, TRUST_RECORD_LEN);
|
||||
if( n != TRUST_RECORD_LEN ) {
|
||||
log_error("trustdb: write failed (n=%d): %s\n", n, strerror(errno) );
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32
|
||||
new_local_id()
|
||||
{
|
||||
off_t offset;
|
||||
u32 recnum;
|
||||
|
||||
/* fixme: look for unused records */
|
||||
offset = lseek( db_fd, 0, SEEK_END );
|
||||
if( offset == -1 )
|
||||
log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
|
||||
recnum = offset / TRUST_RECORD_LEN;
|
||||
assert(recnum); /* this is will never be the first record */
|
||||
return recnum ;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Scan the trustdb for a record of type RECTYPE which maches PKC
|
||||
* The local_id is set to the correct value
|
||||
*/
|
||||
static int
|
||||
scan_record( PKT_public_cert *pkc, TRUSTREC *rec, int rectype )
|
||||
{
|
||||
u32 recnum;
|
||||
u32 keyid[2];
|
||||
byte *fingerprint;
|
||||
size_t fingerlen;
|
||||
int dbg = DBG_TRUST;
|
||||
int rc;
|
||||
|
||||
assert( rectype == 2 || rectype == 3 );
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: scan_record\n");
|
||||
keyid_from_pkc( pkc, keyid );
|
||||
fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
|
||||
assert( fingerlen == 20 || fingerlen == 16 );
|
||||
|
||||
no_io_dbg = 1;
|
||||
for(recnum=1; !(rc=read_record( recnum, rec)); recnum++ ) {
|
||||
if( rec->rectype != rectype )
|
||||
continue;
|
||||
if( rec->rectype == 2 ) {
|
||||
if( rec->r.pubkey.keyid[0] == keyid[0]
|
||||
&& rec->r.pubkey.keyid[1] == keyid[1]
|
||||
&& rec->r.pubkey.algo == pkc->pubkey_algo
|
||||
&& !memcmp(rec->r.pubkey.fingerprint, fingerprint, fingerlen)
|
||||
) { /* found */
|
||||
/* store the local_id */
|
||||
if( pkc->local_id && pkc->local_id != recnum )
|
||||
log_error("%s: found record, but local_id from mem does "
|
||||
"not match recnum (%lu,%lu)\n", db_name,
|
||||
(ulong)pkc->local_id, (ulong)recnum );
|
||||
pkc->local_id = recnum;
|
||||
no_io_dbg = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
log_bug("not yet implemented\n");
|
||||
}
|
||||
no_io_dbg = 0;
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: scan_record: eof or error\n");
|
||||
if( rc != -1 )
|
||||
log_error("%s: scan_record failed: %s\n",db_name, g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -171,7 +434,150 @@ create_db( const char *fname )
|
||||
************* trust logic *******************
|
||||
***********************************************/
|
||||
|
||||
/****************
|
||||
* Verify, that all our public keys are in the trustDB and marked as
|
||||
* ultimately trusted.
|
||||
*/
|
||||
static int
|
||||
verify_own_certs()
|
||||
{
|
||||
int rc;
|
||||
void *enum_context = NULL;
|
||||
PKT_secret_cert *skc = m_alloc_clear( sizeof *skc );
|
||||
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
|
||||
u32 keyid[2];
|
||||
int trust;
|
||||
|
||||
while( !(rc=enum_secret_keys( &enum_context, skc) ) ) {
|
||||
/* fixme: to be sure that it is a secret key of our own,
|
||||
* we should check it, but this needs a passphrase
|
||||
* for every key and this boring for the user.
|
||||
* Solution: Sign the secring and the trustring
|
||||
* and verify this signature during
|
||||
* startup
|
||||
*/
|
||||
|
||||
keyid_from_skc( skc, keyid );
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("checking secret key %08lX\n", (ulong)keyid[1] );
|
||||
|
||||
/* look wether we can access the public key of this secret key */
|
||||
rc = get_pubkey( pkc, keyid );
|
||||
if( rc ) {
|
||||
log_error("keyid %08lX: secret key without public key\n",
|
||||
(ulong)keyid[1] );
|
||||
goto leave;
|
||||
}
|
||||
if( cmp_public_secret_cert( pkc, skc ) ) {
|
||||
log_error("keyid %08lX: secret and public key don't match\n",
|
||||
(ulong)keyid[1] );
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
/* look into the trustdb */
|
||||
rc = check_pkc_trust( pkc, &trust );
|
||||
if( rc ) {
|
||||
log_info("keyid %08lX: problem in trustdb: %s\n", (ulong)keyid[1],
|
||||
g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
if( trust & TRUST_NO_PUBKEY ) {
|
||||
log_info("keyid %08lX: not yet in trustdb\n", (ulong)keyid[1] );
|
||||
/* FIXME: insert */
|
||||
}
|
||||
else if( (trust & TRUST_MASK) != TRUST_ULT_TRUST ) {
|
||||
log_error("keyid %08lX: not marked as ultimately trusted\n",
|
||||
(ulong)keyid[1] );
|
||||
/* FIXME: mark */
|
||||
}
|
||||
|
||||
release_secret_cert_parts( skc );
|
||||
release_public_cert_parts( pkc );
|
||||
}
|
||||
if( rc != -1 )
|
||||
log_error("enum_secret_keys failed: %s\n", g10_errstr(rc) );
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
leave:
|
||||
free_secret_cert( skc );
|
||||
free_public_cert( pkc );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Check all the sigs of the given keyblock and mark them
|
||||
* as checked.
|
||||
*/
|
||||
static int
|
||||
check_sigs( KBNODE keyblock )
|
||||
{
|
||||
KBNODE kbctx;
|
||||
KBNODE node;
|
||||
int rc;
|
||||
|
||||
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE
|
||||
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
||||
rc = check_key_signature( keyblock, node );
|
||||
if( !rc )
|
||||
node->flag |= 1; /* mark signature valid */
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: sig from %08lX: %s\n",
|
||||
rc? g10_errstr(rc): "okay" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Recursive check the signatures.
|
||||
*/
|
||||
static int
|
||||
walk( KBNODE keyblock, int levels )
|
||||
{
|
||||
KBNODE kbctx, node;
|
||||
|
||||
check_sigs( keyblock );
|
||||
if( levels ) { /* check the next level */
|
||||
for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) {
|
||||
if( node->pkt->pkttype == PKT_SIGNATURE && (node->flag & 1) ) {
|
||||
/* read the keyblock for this signator */
|
||||
|
||||
/* and check his signatures */
|
||||
/*walk( his_keyblock, levels-1)*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
check_trust()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -181,11 +587,13 @@ create_db( const char *fname )
|
||||
|
||||
/****************
|
||||
* Perform some checks over the trustdb
|
||||
* level 0: used on initial program startup
|
||||
* level 0: used for initial program startup
|
||||
*/
|
||||
int
|
||||
check_trustdb( int level )
|
||||
{
|
||||
int rc=0;
|
||||
|
||||
if( !level ) {
|
||||
char *fname = make_filename("~/.g10", "trustDB", NULL );
|
||||
if( access( fname, R_OK ) ) {
|
||||
@ -200,13 +608,22 @@ check_trustdb( int level )
|
||||
db_name = fname;
|
||||
|
||||
/* we can verify a signature about our local data (secring and trustdb)
|
||||
* in ~/.g10/ here
|
||||
*/
|
||||
* in ~/.g10/ here */
|
||||
rc = verify_private_data();
|
||||
if( !rc ) {
|
||||
/* verify, that our own certificates are in the trustDB
|
||||
* or move them to the trustdb. */
|
||||
rc = verify_own_certs();
|
||||
|
||||
/* should we check wether there is no other ultimately trusted
|
||||
* key in the database? */
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
log_bug(NULL);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -234,12 +651,171 @@ check_trustdb( int level )
|
||||
int
|
||||
check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel )
|
||||
{
|
||||
TRUSTREC rec;
|
||||
int trustlevel = 0;
|
||||
int rc=0;
|
||||
|
||||
if( opt.verbose )
|
||||
log_info("check_pkc_trust() called.\n");
|
||||
|
||||
/* get the pubkey record */
|
||||
if( pkc->local_id ) {
|
||||
if( read_record( pkc->local_id, &rec ) ) {
|
||||
log_error("check_pkc_trust: read record failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
}
|
||||
else { /* no local_id: scan the trustdb */
|
||||
if( (rc=scan_record( pkc, &rec, 2 )) && rc != -1 ) {
|
||||
log_error("check_pkc_trust: scan_record(2) failed: %s\n",
|
||||
g10_errstr(rc));
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
else if( rc == -1 ) {
|
||||
log_error("check_pkc_trust: pubkey not in TrustDB\n");
|
||||
trustlevel = TRUST_NO_PUBKEY;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
/* fixme: do some additional checks on the pubkey record */
|
||||
|
||||
|
||||
leave:
|
||||
if( opt.verbose )
|
||||
log_info("check_pkc_trust() returns trustlevel %04x.\n", trustlevel);
|
||||
*r_trustlevel = trustlevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Insert a trust record into the TrustDB
|
||||
* This function failes if this record already exists.
|
||||
*/
|
||||
int
|
||||
insert_trust_record( PKT_public_cert *pkc )
|
||||
{
|
||||
TRUSTREC rec;
|
||||
u32 keyid[2];
|
||||
u32 recnum;
|
||||
byte *fingerprint;
|
||||
size_t fingerlen;
|
||||
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: insert_record\n");
|
||||
|
||||
assert( !pkc->local_id );
|
||||
|
||||
keyid_from_pkc( pkc, keyid );
|
||||
fingerprint = fingerprint_from_pkc( pkc, &fingerlen );
|
||||
|
||||
/* FIXME: check that we do not have this record. */
|
||||
|
||||
recnum = new_local_id();
|
||||
/* build record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = 2; /* the pubkey record */
|
||||
rec.r.pubkey.local_id = recnum;
|
||||
rec.r.pubkey.keyid[0] = keyid[0];
|
||||
rec.r.pubkey.keyid[1] = keyid[1];
|
||||
rec.r.pubkey.algo = pkc->pubkey_algo;
|
||||
memcpy(rec.r.pubkey.fingerprint, fingerprint, fingerlen );
|
||||
rec.r.pubkey.ownertrust = 0;
|
||||
if( write_record( recnum, &rec ) ) {
|
||||
log_error("insert_trust_record: write failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
pkc->local_id = recnum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
update_trust_record( PKT_public_cert *pkc, int new_trust )
|
||||
{
|
||||
TRUSTREC rec;
|
||||
u32 keyid[2];
|
||||
u32 recnum;
|
||||
|
||||
if( DBG_TRUST )
|
||||
log_debug("trustdb: update_record\n");
|
||||
|
||||
assert( pkc->local_id );
|
||||
|
||||
if( read_record( pkc->local_id, &rec ) ) {
|
||||
log_error("update_trust_record: read failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
/* check keyid, fingerprint etc ? */
|
||||
|
||||
recnum = new_local_id();
|
||||
/* build record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = 2; /* the pubkey record */
|
||||
rec.r.pubkey.local_id = recnum;
|
||||
rec.r.pubkey.keyid[0] = keyid[0];
|
||||
rec.r.pubkey.keyid[1] = keyid[1];
|
||||
rec.r.pubkey.algo = pkc->pubkey_algo;
|
||||
memcpy(rec.r.pubkey.fingerprint, fingerprint, fingerlen );
|
||||
rec.r.pubkey.ownertrust = 0;
|
||||
if( write_record( recnum, &rec ) ) {
|
||||
log_error("insert_trust_record: write failed\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
pkc->local_id = recnum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
verify_private_data()
|
||||
{
|
||||
int rc = 0;
|
||||
char *sigfile = make_filename("~/.g10", "sig", NULL );
|
||||
|
||||
if( access( sigfile, R_OK ) ) {
|
||||
if( errno != ENOENT ) {
|
||||
log_error("can't access %s: %s\n", sigfile, strerror(errno) );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
goto leave;
|
||||
}
|
||||
log_info("private data signature missing; creating ...\n");
|
||||
rc = sign_private_data();
|
||||
if( rc ) {
|
||||
log_error("error creating %s: %s\n", sigfile, g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: verify this signature */
|
||||
|
||||
leave:
|
||||
m_free(sigfile);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sign_private_data()
|
||||
{
|
||||
int rc;
|
||||
char *sigfile = make_filename("~/.g10", "sig", NULL );
|
||||
char *secring = make_filename("~/.g10", "secring.g10", NULL );
|
||||
STRLIST list = NULL;
|
||||
|
||||
add_to_strlist( &list, db_name );
|
||||
add_to_strlist( &list, secring );
|
||||
|
||||
rc = sign_file( list, 1, NULL, 0, NULL, sigfile);
|
||||
|
||||
m_free(sigfile);
|
||||
m_free(secring);
|
||||
free_strlist(list);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,22 @@
|
||||
#ifndef G10_TRUSTDB_H
|
||||
#define G10_TRUSTDB_H
|
||||
|
||||
|
||||
|
||||
#define TRUST_MASK 0x07 /* for the trust leveles */
|
||||
#define TRUST_UNKNOWN 1 /* unknown */
|
||||
#define TRUST_NO_TRUST 2 /* not trusted */
|
||||
#define TRUST_MARG_TRUST 4 /* marginally trusted */
|
||||
#define TRUST_FULL_TRUST 5 /* fully trusted */
|
||||
#define TRUST_ULT_TRUST 7 /* ultimately trusted */
|
||||
/* other bits used with the trustlevel */
|
||||
#define TRUST_NO_PUBKEY 0x10 /* we do not have the pubkey in out trustDB */
|
||||
|
||||
|
||||
/*-- trustdb.c --*/
|
||||
int check_trustdb( int level );
|
||||
int check_pkc_trust( PKT_public_cert *pkc, int *r_trustlevel );
|
||||
int verify_private_data(void);
|
||||
int sign_private_data(void);
|
||||
|
||||
#endif /*G10_TRUSTDB_H*/
|
||||
|
@ -91,6 +91,7 @@ int answer_is_yes( const char *s );
|
||||
/*-- strgutil.c --*/
|
||||
void free_strlist( STRLIST sl );
|
||||
#define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0)
|
||||
void add_to_strlist( STRLIST *list, const char *string );
|
||||
char *memistr( char *buf, size_t buflen, const char *sub );
|
||||
char *trim_spaces( char *string );
|
||||
int string_count_chr( const char *string, int c );
|
||||
|
@ -37,6 +37,18 @@ free_strlist( STRLIST sl )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
add_to_strlist( STRLIST *list, const char *string )
|
||||
{
|
||||
STRLIST sl;
|
||||
|
||||
sl = m_alloc( sizeof *sl + strlen(string));
|
||||
strcpy(sl->d, string);
|
||||
sl->next = *list;
|
||||
*list = sl;
|
||||
}
|
||||
|
||||
/****************
|
||||
* look for the substring SUB in buffer and return a pointer to that
|
||||
* substring in BUF or NULL if not found.
|
||||
|
Loading…
x
Reference in New Issue
Block a user