1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

some import functionality

This commit is contained in:
Werner Koch 1998-02-16 20:05:02 +00:00
parent f477447d9a
commit 82464369f6
45 changed files with 1299 additions and 324 deletions

View file

@ -1,3 +1,51 @@
Mon Feb 16 20:02:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnode.c (commit_kbnode): New.
(delete_kbnode): removed unused first arg. Changed all Callers.
* ringedit.c (keyblock_resource_name): New.
(get_keyblock_handle): NULL for filename returns default resource.
Mon Feb 16 19:38:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* sig-check.s (check_key_signature): Now uses the supplied
public key to check the signature and not any more the one
from the getkey.c
(do_check): New.
(check_signature): Most work moved to do_check.
Mon Feb 16 14:48:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (find_header): Fixed another bug.
Mon Feb 16 12:18:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (scan_keyring): Add handling of compressed keyrings.
Mon Feb 16 10:44:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c, g10maint.c (strusage): Rewrote.
(build_list): New
Mon Feb 16 08:58:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (use_armor): New.
Sat Feb 14 14:30:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (proc_tree): Sigclass fix.
Sat Feb 14 14:16:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (armor_filter): Changed version and comment string.
* encode.c, sign.c, keygen.c: Changed all comment packet strings.
Sat Feb 14 12:39:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (aGenRevoke): New command.
* revoke.c: New.
* sign.c (make_keysig_packet): Add support for sigclass 0x20.
Fri Feb 13 20:18:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (enum_keyblocks, keyring_enum): New.

View file

@ -45,6 +45,7 @@ common_source = \
plaintext.c \
encr-data.c \
encode.c \
revoke.c \
sig-check.c
g10_SOURCES = g10.c \
@ -53,6 +54,7 @@ g10_SOURCES = g10.c \
g10maint_SOURCES = g10maint.c \
dearmor.c \
$(common_source)
LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@

View file

@ -131,6 +131,7 @@ common_source = \
plaintext.c \
encr-data.c \
encode.c \
revoke.c \
sig-check.c
g10_SOURCES = g10.c \
@ -138,6 +139,7 @@ g10_SOURCES = g10.c \
keygen.c
g10maint_SOURCES = g10maint.c \
dearmor.c \
$(common_source)
LDADD = @INTLLIBS@ $(needed_libs) @ZLIBS@
@ -156,17 +158,17 @@ pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o mdfilter.o \
textfilter.o cipher.o elg.o rsa.o openfile.o keyid.o trustdb.o \
parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o seskey.o \
import.o export.o comment.o status.o sign.o plaintext.o encr-data.o \
encode.o sig-check.o keygen.o
encode.o revoke.o sig-check.o keygen.o
g10_LDADD = $(LDADD)
g10_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \
../util/libutil.a
g10_LDFLAGS =
g10maint_OBJECTS = g10maint.o build-packet.o compress.o free-packet.o \
getkey.o pkclist.o skclist.o ringedit.o kbnode.o mainproc.o armor.o \
mdfilter.o textfilter.o cipher.o elg.o rsa.o openfile.o keyid.o \
trustdb.o parse-packet.o passphrase.o pubkey-enc.o seckey-cert.o \
seskey.o import.o export.o comment.o status.o sign.o plaintext.o \
encr-data.o encode.o sig-check.o
g10maint_OBJECTS = g10maint.o dearmor.o build-packet.o compress.o \
free-packet.o getkey.o pkclist.o skclist.o ringedit.o kbnode.o \
mainproc.o armor.o mdfilter.o textfilter.o cipher.o elg.o rsa.o \
openfile.o keyid.o trustdb.o parse-packet.o passphrase.o pubkey-enc.o \
seckey-cert.o seskey.o import.o export.o comment.o status.o sign.o \
plaintext.o encr-data.o encode.o revoke.o sig-check.o
g10maint_LDADD = $(LDADD)
g10maint_DEPENDENCIES = ../cipher/libcipher.a ../mpi/libmpi.a \
../util/libutil.a
@ -182,15 +184,15 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
DEP_FILES = .deps/armor.P .deps/build-packet.P .deps/cipher.P \
.deps/comment.P .deps/compress.P .deps/elg.P .deps/encode.P \
.deps/encr-data.P .deps/export.P .deps/free-packet.P .deps/g10.P \
.deps/g10maint.P .deps/getkey.P .deps/import.P .deps/kbnode.P \
.deps/keygen.P .deps/keyid.P .deps/mainproc.P .deps/mdfilter.P \
.deps/openfile.P .deps/parse-packet.P .deps/passphrase.P \
.deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P .deps/ringedit.P \
.deps/rsa.P .deps/seckey-cert.P .deps/seskey.P .deps/sig-check.P \
.deps/sign.P .deps/skclist.P .deps/status.P .deps/textfilter.P \
.deps/trustdb.P
.deps/comment.P .deps/compress.P .deps/dearmor.P .deps/elg.P \
.deps/encode.P .deps/encr-data.P .deps/export.P .deps/free-packet.P \
.deps/g10.P .deps/g10maint.P .deps/getkey.P .deps/import.P \
.deps/kbnode.P .deps/keygen.P .deps/keyid.P .deps/mainproc.P \
.deps/mdfilter.P .deps/openfile.P .deps/parse-packet.P \
.deps/passphrase.P .deps/pkclist.P .deps/plaintext.P .deps/pubkey-enc.P \
.deps/revoke.P .deps/ringedit.P .deps/rsa.P .deps/seckey-cert.P \
.deps/seskey.P .deps/sig-check.P .deps/sign.P .deps/skclist.P \
.deps/status.P .deps/textfilter.P .deps/trustdb.P
SOURCES = $(g10_SOURCES) $(g10maint_SOURCES)
OBJECTS = $(g10_OBJECTS) $(g10maint_OBJECTS)

View file

@ -36,8 +36,6 @@
#include "status.h"
#define CRCINIT 0xB704CE
#define CRCPOLY 0X864CFB
#define CRCUPDATE(a,c) do { \
@ -163,6 +161,29 @@ is_armored( byte *buf )
return 1;
}
/****************
* Try to check wether the iobuf is armored
* Returns true if this may be the case; the caller should use the
* filter to do further processing.
*/
int
use_armor_filter( IOBUF a )
{
byte buf[1];
int n;
n = iobuf_peek(a, buf, 1 );
if( n == -1 )
return 0; /* EOF, doesn't matter wether armored or not */
if( !n )
return 1; /* can't check it: try armored */
return is_armored(buf);
}
static void
invalid_armor(void)
{
@ -248,7 +269,9 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
c = 0;
for(n=0; n < 28 && (c=iobuf_get2(a)) != -1 && c != '\n'; )
buf[n++] = c;
if( !n || c == -1 )
if( !n && c == '\n' )
state = fhdrCHECKBegin;
else if( !n || c == -1 )
state = fhdrNOArmor; /* too short */
else if( !is_armored( buf ) )
state = fhdrNOArmor;
@ -269,8 +292,12 @@ find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
break;
case fhdrINITSkip:
while( (c=iobuf_get2(a)) != -1 && c != '\n' )
;
if( c == '\n' )
n = 0;
else {
while( (c=iobuf_get2(a)) != -1 && c != '\n' )
;
}
state = c == -1? fhdrEOF : fhdrINIT;
break;
@ -912,8 +939,9 @@ armor_filter( void *opaque, int control,
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: G10 pre-release " VERSION "\n");
iobuf_writestr(a, "Comment: This is an alpha test version!\n\n");
iobuf_writestr(a, "Version: G10 v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
iobuf_writestr(a, "Comment: This is an alpha version!\n\n");
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
@ -1012,3 +1040,5 @@ armor_filter( void *opaque, int control,
return rc;
}

View file

@ -106,7 +106,8 @@ encode_simple( const char *filename, int mode )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
write_comment( out, "#Created by G10 pre-release " VERSION );
write_comment( out, "#created by G10 v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
@ -192,7 +193,8 @@ encode_crypt( const char *filename, STRLIST remusr )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
write_comment( out, "#Created by G10 pre-release " VERSION );
write_comment( out, "#created by G10 v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );

View file

@ -79,6 +79,7 @@ int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
void free_md_filter_context( md_filter_context_t *mfx );
/*-- armor.c --*/
int use_armor_filter( IOBUF a );
int armor_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len);

109
g10/g10.c
View file

@ -61,6 +61,7 @@ static ARGPARSE_OPTS opts[] = {
{ 505, "delete-key",0, N_("remove key from the public keyring")},
{ 524, "edit-sig" ,0, N_("edit a key signature")},
{ 525, "change-passphrase", 0, N_("change the passphrase of your secret keyring")},
{ 542, "gen-revoke",0, N_("generate a revocation certificate")},
{ 537, "export" , 0, N_("export keys") },
{ 530, "import", 0 , N_("import/merge keys")},
@ -119,49 +120,90 @@ enum cmd_values { aNull = 0,
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
aSignKey, aClearsign, aListPackets, aEditSig,
aKMode, aKModeC, aChangePass, aImport,
aExport, aCheckKeys,
aExport, aCheckKeys, aGenRevoke,
aNOP };
static char *build_list( const char *text,
const char *(*mapf)(int), int (*chkf)(int) );
static void set_cmd( enum cmd_values *ret_cmd,
enum cmd_values new_cmd );
const char *
strusage( int level )
{
static char *digests, *pubkeys, *ciphers;
const char *p;
switch( level ) {
case 10:
case 0: p = "g10 - v" VERSION "; "
"Copyright 1998 Werner Koch (dd9jn)\n" ; break;
case 13: p = "g10"; break;
case 14: p = VERSION; break;
case 11: p = "g10"; break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _(
"Please report bugs to <g10-bugs@isil.d.shuttle.de>."
); break;
case 1:
case 11: p = "Usage: g10 [options] [files] (-h for help)";
break;
case 2:
case 12: p =
_("Syntax: g10 [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"); break;
case 40: p = _(
"Usage: g10 [options] [files] (-h for help)"
); break;
case 41: p = _(
"Syntax: g10 [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
); break;
case 26:
p = _("Please report bugs to <g10-bugs@isil.d.shuttle.de>.\n");
case 31: p = "\n"; break;
case 32:
if( !ciphers )
ciphers = build_list("Supported ciphers: ", cipher_algo_to_string,
check_cipher_algo );
p = ciphers;
break;
case 33:
if( !pubkeys )
pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string,
check_pubkey_algo );
p = pubkeys;
break;
case 34:
if( !digests )
digests = build_list("Supported digests: ", digest_algo_to_string,
check_digest_algo );
p = digests;
break;
#if defined(HAVE_RSA_CIPHER)
case 30: p = _(
"WARNING: This version has RSA support! Your are not allowed to\n"
" use it inside the Unites States before Sep 30, 2000!\n" );
#else
case 30: p = "";
#endif
break;
default: p = default_strusage(level);
}
return p;
}
static char *
build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
{
int i;
const char *s;
size_t n=strlen(text)+2;
char *list, *p;
for(i=1; i < 100; i++ )
if( !chkf(i) && (s=mapf(i)) )
n += strlen(s) + 2;
list = m_alloc( 21 + n ); *list = 0;
for(p=NULL, i=1; i < 100; i++ ) {
if( !chkf(i) && (s=mapf(i)) ) {
if( !p )
p = stpcpy( list, text );
else
p = stpcpy( p, ", ");
p = stpcpy(p, s );
}
}
if( p )
p = stpcpy(p, "\n" );
return list;
}
static void
i18n_init(void)
{
@ -257,7 +299,6 @@ main( int argc, char **argv )
STRLIST sl, remusr= NULL, locusr=NULL;
int nrings=0, sec_nrings=0;
armor_filter_context_t afx;
const char *s;
int detached_sig = 0;
FILE *configfp = NULL;
char *configname = NULL;
@ -405,6 +446,7 @@ main( int argc, char **argv )
case 539: set_cmd( &cmd, aClearsign); break;
case 540: secmem_set_flags( secmem_get_flags() | 1 ); break;
case 541: set_cmd( &cmd, aNOP); break;
case 542: set_cmd( &cmd, aGenRevoke); break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@ -420,10 +462,8 @@ main( int argc, char **argv )
g10_exit(2);
if( greeting ) {
if( *(s=strusage(10)) )
tty_printf("%s", s);
if( *(s=strusage(30)) )
tty_printf("%s", s);
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
tty_printf("%s", strusage(15) );
}
/* initialize the secure memory. */
@ -630,6 +670,12 @@ main( int argc, char **argv )
free_strlist(sl);
break;
case aGenRevoke:
if( argc != 1 )
wrong_args("--gen-revoke user-id");
gen_revoke( *argv );
break;
case aNOP:
break;
@ -642,9 +688,10 @@ main( int argc, char **argv )
log_error(_("can't open '%s'\n"), fname_print);
else {
if( !opt.no_armor ) {
/* push the armor filter, so it can peek at the input data */
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
if( use_armor_filter( a ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
}
if( cmd == aListPackets ) {
set_packet_list_mode(1);

View file

@ -43,51 +43,92 @@
enum cmd_values { aNull = 0,
aPrimegen, aPrintMDs, aListPackets, aKMode, aKModeC,
aListTrustDB, aListTrustPath,
aListTrustDB, aListTrustPath, aDeArmor,
aTest };
static char *build_list( const char *text,
const char *(*mapf)(int), int (*chkf)(int) );
static void set_cmd( enum cmd_values *ret_cmd,
enum cmd_values new_cmd );
static void print_hex( byte *p, size_t n );
static void print_mds( const char *fname );
static void do_test(int);
const char *
strusage( int level )
{
static char *digests, *pubkeys, *ciphers;
const char *p;
switch( level ) {
case 10:
case 0: p = "g10maint - v" VERSION "; "
"Copyright 1997 Werner Koch (dd9jn)\n" ; break;
case 13: p = "g10"; break;
case 14: p = VERSION; break;
case 11: p = "g10maint"; break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _(
"Please report bugs to <g10-bugs@isil.d.shuttle.de>."
); break;
case 1:
case 11: p = "Usage: g10main [options] (-h for help)";
break;
case 2:
case 12: p =
_("Syntax: g10maint [options]\n"
"The G10 maintenace utility\n"); break;
case 40: p = _(
"Usage: g10maint [options] [files] (-h for help)"
); break;
case 41: p = _(
"Syntax: g10maint [options] [files]\n"
"G10 maintenance utility\n"
); break;
case 26:
p = _("Please report bugs to <g10-bugs@isil.d.shuttle.de>.\n");
case 31: p = "\n"; break;
case 32:
if( !ciphers )
ciphers = build_list("Supported ciphers: ", cipher_algo_to_string,
check_cipher_algo );
p = ciphers;
break;
case 33:
if( !pubkeys )
pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string,
check_pubkey_algo );
p = pubkeys;
break;
case 34:
if( !digests )
digests = build_list("Supported digests: ", digest_algo_to_string,
check_digest_algo );
p = digests;
break;
#if defined(HAVE_RSA_CIPHER)
case 30: p = _(
"WARNING: This version has RSA support! Your are not allowed to\n"
" use it inside the Unites States before Sep 30, 2000!\n" );
#else
case 30: p = "";
#endif
break;
default: p = default_strusage(level);
}
return p;
}
static char *
build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
{
int i;
const char *s;
size_t n=strlen(text)+2;
char *list, *p;
for(i=1; i < 100; i++ )
if( !chkf(i) && (s=mapf(i)) )
n += strlen(s) + 2;
list = m_alloc( 21 + n ); *list = 0;
for(p=NULL, i=1; i < 100; i++ ) {
if( !chkf(i) && (s=mapf(i)) ) {
if( !p )
p = stpcpy( list, text );
else
p = stpcpy( p, ", ");
p = stpcpy(p, s );
}
}
if( p )
p = stpcpy(p, "\n" );
return list;
}
static void
i18n_init(void)
{
@ -178,6 +219,7 @@ main( int argc, char **argv )
{ 535, "completes-needed", 1, N_("(default is 1)")},
{ 536, "marginals-needed", 1, N_("(default is 3)")},
{ 538, "trustdb-name", 2, "\r" },
{ 540, "dearmor", 0, N_("De-Armor a file or stdin") },
{0} };
ARGPARSE_ARGS pargs;
@ -189,7 +231,6 @@ main( int argc, char **argv )
STRLIST remusr= NULL, locusr=NULL;
int nrings=0, sec_nrings=0;
armor_filter_context_t afx;
const char *s;
FILE *configfp = NULL;
char *configname = NULL;
unsigned configlineno;
@ -308,6 +349,7 @@ main( int argc, char **argv )
case 535: opt.completes_needed = pargs.r.ret_int; break;
case 536: opt.marginals_needed = pargs.r.ret_int; break;
case 538: trustdb_name = pargs.r.ret_str; break;
case 540: set_cmd( &cmd, aDeArmor); break;
default : errors++; pargs.err = configfp? 1:2; break;
}
}
@ -360,10 +402,8 @@ main( int argc, char **argv )
if( opt.verbose > 1 )
set_packet_list_mode(1);
if( greeting ) {
if( *(s=strusage(10)) )
tty_printf("%s", s);
if( *(s=strusage(30)) )
tty_printf("%s", s);
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
tty_printf("%s", strusage(15) );
}
if( !sec_nrings || default_keyring ) { /* add default secret rings */
@ -436,6 +476,15 @@ main( int argc, char **argv )
usage(1);
break;
case aDeArmor:
if( argc > 1 )
wrong_args("--dearmor [file]");
rc = dearmor_file( argc? *argv: NULL );
if( rc )
log_error(_("dearmoring failed: %s\n"), g10_errstr(rc));
break;
case aPrimegen:
if( argc == 1 ) {
mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1);

View file

@ -460,6 +460,7 @@ static int
scan_keyring( PKT_public_cert *pkc, u32 *keyid,
const char *name, const char *filename )
{
compress_filter_context_t cfx;
int rc=0;
int found = 0;
IOBUF a;
@ -499,6 +500,19 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
log_error("Hmmm, pubkey without an user id in '%s'\n", filename);
goto leave;
}
else if( pkt.pkttype == PKT_COMPRESSED ) {
memset( &cfx, 0, sizeof cfx );
if( pkt.pkt.compressed->algorithm == 1 )
cfx.pgpmode = 1;
else if( pkt.pkt.compressed->algorithm != 2 ){
rc = G10ERR_COMPR_ALGO;
log_error("compressed keyring: %s\n", g10_errstr(rc) );
break;
}
pkt.pkt.compressed->buf = NULL;
iobuf_push_filter( a, compress_filter, &cfx );
}
else if( keyid && pkt.pkttype == PKT_PUBLIC_CERT ) {
switch( pkt.pkt.public_cert->pubkey_algo ) {
case PUBKEY_ALGO_ELGAMAL:

View file

@ -32,6 +32,15 @@
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "main.h"
static int read_block( IOBUF a, compress_filter_context_t *cfx,
PACKET **pending_pkt, KBNODE *ret_root );
static int import_one( const char *fname, KBNODE keyblock );
static int chk_self_sigs( const char *fname, KBNODE keyblock,
PKT_public_cert *pkc, u32 *keyid );
static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid );
/****************
@ -40,11 +49,11 @@
* least one userid. Only user ids which are self signed will be imported.
* Other signatures are not not checked.
*
* Actually this functtion does a merge, it works like this:
* Actually this functtion does a merge. It works like this:
* FIXME: add handling for revocation certs
*
* - get the keyblock
* - check self-signatures and remove all userids and their isgnatures
* - check self-signatures and remove all userids and their signatures
* without/invalid self-signatures.
* - reject the keyblock, if we have no valid userid.
* - See wether we have this key already in one of our pubrings.
@ -55,7 +64,7 @@
* - See wether we have only non-self-signature on one user id; if not
* ask the user what to do.
* - compare the signatures: If we already have this signature, check
* that they compare okay, if not issue a warning and ask the user.
* that they compare okay; if not, issue a warning and ask the user.
* (consider to look at the timestamp and use the newest?)
* - Simply add the signature. Can't verify here because we may not have
* the signatures public key yet; verification is done when putting it
@ -65,10 +74,298 @@
*
*/
int
import_pubkeys( const char *filename )
import_pubkeys( const char *fname )
{
log_fatal("Not yet implemented");
return 0;
armor_filter_context_t afx;
compress_filter_context_t cfx;
PACKET *pending_pkt = NULL;
IOBUF inp = NULL;
KBNODE keyblock;
int rc = 0;
memset( &afx, 0, sizeof afx);
memset( &cfx, 0, sizeof cfx);
/* open file */
inp = iobuf_open(fname);
if( !fname )
fname = "[stdin]";
if( !inp ) {
log_error("%s: can't open file: %s\n", fname, strerror(errno) );
return G10ERR_OPEN_FILE;
}
if( !opt.no_armor ) /* armored reading is not diabled */
iobuf_push_filter( inp, armor_filter, &afx );
while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) {
if( keyblock->pkt->pkttype == PKT_PUBLIC_CERT )
rc = import_one( fname, keyblock );
else
log_info("%s: skipping block of type %d\n",
fname, keyblock->pkt->pkttype );
release_kbnode(keyblock);
if( rc )
break;
}
if( rc == -1 )
rc = 0;
else if( rc )
log_error("%s: read error: %s\n", fname, g10_errstr(rc));
iobuf_close(inp);
return rc;
}
/****************
* Read the next keyblock from stream A, CFX is used to handle
* compressed keyblocks. PENDING_PKT should be initialzed to NULL
* and not chnaged form the caller.
* Retunr: 0 = okay, -1 no more blocks or another errorcode.
*/
static int
read_block( IOBUF a, compress_filter_context_t *cfx,
PACKET **pending_pkt, KBNODE *ret_root )
{
int rc;
PACKET *pkt;
KBNODE root = NULL;
int in_cert = 0;
if( *pending_pkt ) {
root = new_kbnode( *pending_pkt );
*pending_pkt = NULL;
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_block: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
free_packet( pkt );
init_packet(pkt);
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_COMPRESSED:
if( pkt->pkt.compressed->algorithm == 1 )
cfx->pgpmode = 1;
else if( pkt->pkt.compressed->algorithm != 2 ){
rc = G10ERR_COMPR_ALGO;
goto ready;
}
pkt->pkt.compressed->buf = NULL;
iobuf_push_filter( a, compress_filter, cfx );
free_packet( pkt );
init_packet(pkt);
break;
case PKT_PUBLIC_CERT:
case PKT_SECRET_CERT:
if( in_cert ) { /* store this packet */
*pending_pkt = pkt;
pkt = NULL;
goto ready;
}
in_cert = 1;
default:
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
}
ready:
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
return rc;
}
/****************
* Try to import one keyblock. Return an error only in serious cases, but
* never for an invalid keyblock. It uses log_error to increase the
* internal errorcount, so that invalid input can be detected by programs
* which called g10.
*/
static int
import_one( const char *fname, KBNODE keyblock )
{
PKT_public_cert *pkc;
PKT_public_cert *pkc_orig;
KBNODE node, uidnode;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
/* get the key and print some infos about it */
node = find_kbnode( keyblock, PKT_PUBLIC_CERT );
if( !node ) {
log_error("%s: Oops; public key not found anymore!\n", fname);
return G10ERR_GENERAL; /* really serious */
}
pkc = node->pkt->pkt.public_cert;
keyid_from_pkc( pkc, keyid );
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
if( opt.verbose ) {
log_info("%s: pub %4u%c/%08lX %s ", fname,
nbits_from_pkc( pkc ),
pubkey_letter( pkc->pubkey_algo ),
(ulong)keyid[1], datestr_from_pkc(pkc) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len );
putc('\n', stderr);
}
if( !uidnode ) {
log_error("%s: No user id for key %08lX\n", fname, (ulong)keyid[1]);
return 0;
}
clear_kbnode_flags( keyblock );
rc = chk_self_sigs( fname, keyblock , pkc, keyid );
if( rc )
return rc== -1? 0:rc;
if( !delete_inv_parts( fname, keyblock, keyid ) ) {
log_info("%s: key %08lX, no valid user ids left over\n",
fname, (ulong)keyid[1]);
return 0;
}
/* do we have this key already in one of our pubrings ? */
pkc_orig = m_alloc( sizeof *pkc_orig );
rc = get_pubkey( pkc_orig, keyid );
if( rc && rc != G10ERR_NO_PUBKEY ) {
log_error("%s: key %08lX, public key not found: %s\n",
fname, (ulong)keyid[1], g10_errstr(rc));
}
else if( rc ) { /* inset this key */
/* get default resource */
if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
log_error("no default public keyring\n");
return G10ERR_GENERAL;
}
if( opt.verbose > 1 )
log_info("%s: writing to '%s'\n",
fname, keyblock_resource_name(&kbpos) );
if( (rc=lock_keyblock( &kbpos )) )
log_error("can't lock public keyring '%s': %s\n",
keyblock_resource_name(&kbpos), g10_errstr(rc) );
else if( (rc=insert_keyblock( &kbpos, keyblock )) )
log_error("%s: can't write to '%s': %s\n", fname,
keyblock_resource_name(&kbpos), g10_errstr(rc) );
unlock_keyblock( &kbpos );
/* we are ready */
if( opt.verbose )
log_info("%s: key %08lX imported\n", fname, (ulong)keyid[1]);
}
else {
/* merge
* o Compare the key and the self-signatures of the new and the one in
* our keyring. If they are different something weird is going on;
* ask what to do.
* o See wether we have only non-self-signature on one user id; if not
* ask the user what to do.
* o compare the signatures: If we already have this signature, check
* that they compare okay; if not, issue a warning and ask the user.
* (consider to look at the timestamp and use the newest?)
* o Simply add the signature. Can't verify here because we may not have
* the signatures public key yet; verification is done when putting it
* into the trustdb, which is done automagically as soon as this pubkey
* is used.
*/
log_error("nyi\n");
}
free_public_cert( pkc_orig );
return rc;
}
/****************
* loop over the keyblock an check all self signatures.
* Mark all user-ids with a self-signature by setting flag bit 0.
* Mark all user-ids with an invalid self-signature by setting bit 1.
*/
static int
chk_self_sigs( const char *fname, KBNODE keyblock,
PKT_public_cert *pkc, u32 *keyid )
{
KBNODE n, unode;
PKT_signature *sig;
int rc;
for( n=keyblock; (n = find_next_kbnode(n, 0)); ) {
if( n->pkt->pkttype != PKT_SIGNATURE )
continue;
sig = n->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
unode = find_prev_kbnode( keyblock, n, PKT_USER_ID );
if( !unode ) {
log_error("%s: key %08lX, no user-id for signature\n",
fname, (ulong)keyid[1]);
return -1; /* the complete keyblock is invalid */
}
rc = check_key_signature( keyblock, n, NULL);
if( rc ) {
log_error("%s: key %08lX, invalid self-signature\n",
fname, (ulong)keyid[1]);
unode->flag |= 2; /* mark as invalid */
}
unode->flag |= 1; /* mark that user-id checked */
}
}
return 0;
}
/****************
* delete all parts which are invalid.
* returns: true if at least one valid user-id is left over.
*/
static int
delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
{
KBNODE node;
int nvalid=0;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( (node->flag & 2) || !(node->flag & 1) ) {
log_info("%s: key %08lX, removed userid '",
fname, (ulong)keyid[1]);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len );
fputs("'\n", stderr );
delete_kbnode( node ); /* the user-id */
/* and all following packets up to the next user-id */
while( node->next && node->next->pkt->pkttype != PKT_USER_ID ){
delete_kbnode( node->next );
node = node->next;
}
}
else
nvalid++;
}
}
/* note: because keyblock is the public key, ist is never marked
* for deletion and so the keyblock cannot chnage */
commit_kbnode( &keyblock );
return nvalid;
}

View file

@ -61,7 +61,7 @@ release_kbnode( KBNODE n )
* Note: This does only work with walk_kbnode!!
*/
void
delete_kbnode( KBNODE root, KBNODE node )
delete_kbnode( KBNODE node )
{
node->private_flag |= 1;
}
@ -196,3 +196,29 @@ clear_kbnode_flags( KBNODE n )
}
}
/****************
* Commit changes made to the kblist at ROOT. Note that ROOT my change,
* and it is therefor passed by reference.
* The function has the effect of removing all nodes marked as deleted.
* returns true, if any node has been changed
*/
int
commit_kbnode( KBNODE *root )
{
KBNODE n, n2;
int changed = 0;
for(n=*root; n; n = n2 ) {
n2 = n->next;
if( (n->private_flag & 1) ) {
if( n == *root )
*root = n2;
free_packet( n->pkt );
m_free( n );
changed = 1;
}
}
return changed;
}

View file

@ -128,7 +128,7 @@ byte *fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len );
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
void release_kbnode( KBNODE n );
void delete_kbnode( KBNODE root, KBNODE node );
void delete_kbnode( KBNODE node );
void add_kbnode( KBNODE root, KBNODE node );
void insert_kbnode( KBNODE root, KBNODE node, int pkttype );
KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype );
@ -136,9 +136,11 @@ KBNODE find_next_kbnode( KBNODE node, int pkttype );
KBNODE find_kbnode( KBNODE node, int pkttype );
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
void clear_kbnode_flags( KBNODE n );
int commit_kbnode( KBNODE *root );
/*-- ringedit.c --*/
int add_keyblock_resource( const char *filename, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
int find_keyblock_byname( KBPOS *kbpos, const char *username );

View file

@ -538,8 +538,8 @@ generate_keypair()
* The first packet is a dummy comment packet which we flag
* as deleted. The very first packet must always be a CERT packet.
*/
pub_root = make_comment_node("#"); delete_kbnode(pub_root, pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root, sec_root);
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
@ -559,9 +559,11 @@ generate_keypair()
BUG();
if( !rc ) {
add_kbnode( pub_root,
make_comment_node("#created by G10 release " VERSION ));
make_comment_node("#created by G10 v" VERSION " ("
PRINTABLE_OS_NAME ")"));
add_kbnode( sec_root,
make_comment_node("#created by G10 release " VERSION ));
make_comment_node("#created by G10 v" VERSION " ("
PRINTABLE_OS_NAME ")"));
}
if( !rc )
write_uid(pub_root, uid );

View file

@ -89,6 +89,10 @@ void g10_rsa_sign( PKT_secret_cert *skc, PKT_signature *sig,
int import_pubkeys( const char *filename );
/*-- export.c --*/
int export_pubkeys( STRLIST users );
/* dearmor.c --*/
int dearmor_file( const char *fname );
/*-- revoke.c --*/
int gen_revoke( const char *uname );
#endif /*G10_MAIN_H*/

View file

@ -619,15 +619,17 @@ proc_tree( CTX c, KBNODE node )
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
log_info("proc_tree: old style signature\n");
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
c->mfx.md = md_open(digest_algo_from_sig(sig), 0);
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
if( !c->have_data && (sig->sig_class&~3) == 0x10 ) {
log_info("old style signature\n");
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
c->mfx.md = md_open(digest_algo_from_sig(sig), 0);
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
}
}
}

199
g10/revoke.c Normal file
View file

@ -0,0 +1,199 @@
/* revoke.c
* Copyright (c) 1998 by Werner Koch (dd9jn)
*
* This file is part of G10.
*
* G10 is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* G10 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "ttyio.h"
/****************
* Generate a revocation certificate for UNAME
*/
int
gen_revoke( const char *uname )
{
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
PACKET pkt;
PKT_secret_cert *skc; /* used as pointer into a kbnode */
PKT_public_cert *pkc = NULL;
PKT_signature *sig = NULL;
u32 skc_keyid[2];
IOBUF out = NULL;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
char *answer;
int yes;
if( opt.batch ) {
log_error("sorry, can't do this in batch mode\n");
return G10ERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
/* search the userid */
rc = find_secret_keyblock_byname( &kbpos, uname );
if( rc ) {
log_error("secret key for user '%s' not found\n", uname );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("error reading the certificate: %s\n", g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, PKT_SECRET_CERT );
if( !node ) { /* maybe better to use log_bug ? */
log_error("Oops; secret key not found anymore!\n");
rc = G10ERR_GENERAL;
goto leave;
}
/* FIXME: should make a function out of this stuff,
* it's used all over the source */
skc = node->pkt->pkt.secret_cert;
keyid_from_skc( skc, skc_keyid );
tty_printf("\nsec %4u%c/%08lX %s ",
nbits_from_skc( skc ),
pubkey_letter( skc->pubkey_algo ),
skc_keyid[1], datestr_from_skc(skc) );
{
size_t n;
char *p = get_user_id( skc_keyid, &n );
tty_print_string( p, n );
m_free(p);
tty_printf("\n");
}
/* the the pkc */
pkc = m_alloc_clear( sizeof *pkc );
rc = get_pubkey( pkc, skc_keyid );
if( rc ) {
log_error("no corresponding public key: %s\n", g10_errstr(rc) );
goto leave;
}
if( cmp_public_secret_cert( pkc, skc ) ) {
log_error("public key does not match secret key!\n" );
rc = G10ERR_GENERAL;
goto leave;
}
tty_printf("\n");
answer = tty_get("Create a revocation certificate for this key? ");
tty_kill_prompt();
yes = answer_is_yes(answer);
m_free(answer);
if( !yes ) {
rc = 0;
goto leave;
}
switch( is_secret_key_protected( skc ) ) {
case -1:
log_error("unknown protection algorithm\n");
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
tty_printf("Warning: This key is not protected!\n");
break;
default:
rc = check_secret_key( skc );
break;
}
if( rc )
goto leave;
if( !opt.armor )
tty_printf("ASCII armored output forced.\n");
if( !(out = open_outfile( NULL, 0 )) ) {
rc = G10ERR_CREATE_FILE;
goto leave;
}
afx.what = 1;
iobuf_push_filter( out, armor_filter, &afx );
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
/* create it */
rc = make_keysig_packet( &sig, pkc, NULL, skc, 0x20, DIGEST_ALGO_RMD160);
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
goto leave;
}
init_packet( &pkt );
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( rc ) {
log_error("build_packet failed: %s\n", g10_errstr(rc) );
goto leave;
}
/* and issue a usage notice */
tty_printf("Revocation certificate created.\n\n"
"Please move it to a media, which you can hide away; if Mallory gets\n"
"access to this certificate he can use it to make your key unusable.\n"
"It is clever to print this certificate and store it away, just in the case\n"
"your media gets unreadable. But have some caution: The printer system of\n"
"your machine might store the data and make it availabe to others!\n");
leave:
if( pkc )
free_public_cert( pkc );
if( sig )
free_seckey_enc( sig );
release_kbnode( keyblock );
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
return rc;
}

View file

@ -123,10 +123,24 @@ add_keyblock_resource( const char *filename, int force, int secret )
return 0;
}
/****************
* Return the resource name of the keyblock associated with KBPOS.
*/
const char *
keyblock_resource_name( KBPOS *kbpos )
{
RESTBL *rentry;
if( !(rentry = check_pos( kbpos )) || !rentry->fname )
log_bug("no name for keyblock resource %d\n", kbpos->resno );
return rentry->fname;
}
/****************
* Get a keyblock handle KBPOS from a filename. This can be used
* to get a handle for insert_keyblock for a new keyblock.
* Using a filename of NULL returns the default resource
*/
int
get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
@ -136,7 +150,7 @@ get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
for(i=0; i < MAX_RESOURCES; i++ )
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
/* fixme: dos needs case insensitive file compare */
if( !strcmp( resource_table[i].fname, filename ) ) {
if( !filename || !strcmp( resource_table[i].fname, filename ) ) {
memset( kbpos, 0, sizeof *kbpos );
kbpos->resno = i;
return 0;
@ -598,6 +612,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
}
kbpos->count++;
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */
@ -660,6 +675,7 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root )
goto ready;
}
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */

View file

@ -121,7 +121,8 @@ do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits,
MPI a;
if( len + asnlen + 4 > nframe )
log_bug("can't encode a %d bit MD into a %d bits frame\n",len*8, nbits);
log_bug("can't encode a %d bit MD into a %d bits frame\n",
(int)(len*8), (int)nbits);
/* We encode the MD in this way:
*

View file

@ -32,6 +32,10 @@
#include "main.h"
static int do_check( PKT_public_cert *pkc, PKT_signature *sig,
MD_HANDLE digest );
/****************
* Check the signature which is contained in the rsa_integer.
* The md5handle should be currently open, so that this function
@ -41,14 +45,23 @@ int
signature_check( PKT_signature *sig, MD_HANDLE digest )
{
PKT_public_cert *pkc = m_alloc_clear( sizeof *pkc );
MPI result = NULL;
int rc=0;
if( get_pubkey( pkc, sig->keyid ) ) {
if( get_pubkey( pkc, sig->keyid ) )
rc = G10ERR_NO_PUBKEY;
goto leave;
}
else
rc = do_check( pkc, sig, digest );
free_public_cert( pkc );
return rc;
}
static int
do_check( PKT_public_cert *pkc, PKT_signature *sig, MD_HANDLE digest )
{
MPI result = NULL;
int rc=0;
if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
ELG_public_key pkey;
@ -164,8 +177,6 @@ signature_check( PKT_signature *sig, MD_HANDLE digest )
leave:
if( pkc )
free_public_cert( pkc );
mpi_free( result );
return rc;
}
@ -217,7 +228,7 @@ check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
md = md_open( algo, 0 );
hash_public_cert( md, pkc );
md_write( md, uid->name, uid->len );
rc = signature_check( sig, md );
rc = do_check( pkc, sig, md );
md_close(md);
}
else {

View file

@ -152,7 +152,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( opt.armor && !outfile )
iobuf_push_filter( out, armor_filter, &afx );
write_comment( out, "#Created by G10 pre-release " VERSION );
write_comment( out, "#created by G10 v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.compress && !outfile )
iobuf_push_filter( out, compress_filter, &zfx );
@ -629,7 +630,7 @@ remove_keysigs( KBNODE keyblock, int all )
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 1)) ; ) {
if( node->flag & 128)
delete_kbnode( keyblock, node );
delete_kbnode(node );
}
return 1;
@ -969,6 +970,7 @@ change_passphrase( const char *username )
/****************
* Create a signature packet for the given public key certificate
* and the user id and return it in ret_sig. User signature class SIGCLASS
* user-id is not used (and may be NULL if sigclass is 0x20)
*/
int
make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
@ -979,11 +981,12 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
int rc=0;
MD_HANDLE md;
assert( sigclass >= 0x10 && sigclass <= 0x13 );
assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x20 );
md = md_open( digest_algo, 0 );
/* hash the public key certificate and the user id */
hash_public_cert( md, pkc );
md_write( md, uid->name, uid->len );
if( sigclass != 0x20 )
md_write( md, uid->name, uid->len );
/* and make the signature packet */
sig = m_alloc_clear( sizeof *sig );
sig->pubkey_algo = skc->pubkey_algo;