aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog48
-rw-r--r--g10/Makefile.am2
-rw-r--r--g10/Makefile.in34
-rw-r--r--g10/armor.c44
-rw-r--r--g10/encode.c6
-rw-r--r--g10/filter.h1
-rw-r--r--g10/g10.c111
-rw-r--r--g10/g10maint.c105
-rw-r--r--g10/getkey.c14
-rw-r--r--g10/import.c307
-rw-r--r--g10/kbnode.c28
-rw-r--r--g10/keydb.h4
-rw-r--r--g10/keygen.c10
-rw-r--r--g10/main.h4
-rw-r--r--g10/mainproc.c20
-rw-r--r--g10/revoke.c199
-rw-r--r--g10/ringedit.c18
-rw-r--r--g10/seskey.c3
-rw-r--r--g10/sig-check.c27
-rw-r--r--g10/sign.c11
20 files changed, 877 insertions, 119 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 2bfa48b74..4e1cf4329 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,51 @@
+Mon Feb 16 20:02:03 1998 Werner Koch ([email protected])
+
+ * 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 ([email protected])
+
+ * 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 ([email protected])
+
+ * armor.c (find_header): Fixed another bug.
+
+Mon Feb 16 12:18:34 1998 Werner Koch ([email protected])
+
+ * getkey.c (scan_keyring): Add handling of compressed keyrings.
+
+Mon Feb 16 10:44:51 1998 Werner Koch ([email protected])
+
+ * g10.c, g10maint.c (strusage): Rewrote.
+ (build_list): New
+
+Mon Feb 16 08:58:41 1998 Werner Koch ([email protected])
+
+ * armor.c (use_armor): New.
+
+Sat Feb 14 14:30:57 1998 Werner Koch ([email protected])
+
+ * mainproc.c (proc_tree): Sigclass fix.
+
+Sat Feb 14 14:16:33 1998 Werner Koch ([email protected])
+
+ * 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 ([email protected])
+
+ * 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 ([email protected])
* ringedit.c (enum_keyblocks, keyring_enum): New.
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 128d594cd..e200fcd1d 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -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@
diff --git a/g10/Makefile.in b/g10/Makefile.in
index afbeebf8f..953b13b6b 100644
--- a/g10/Makefile.in
+++ b/g10/Makefile.in
@@ -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)
diff --git a/g10/armor.c b/g10/armor.c
index 1b31f6263..17dc444b8 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -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;
}
+
+
diff --git a/g10/encode.c b/g10/encode.c
index eea7345fa..5726bc2b7 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -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 );
diff --git a/g10/filter.h b/g10/filter.h
index b49ce28b7..93e72ce9c 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -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);
diff --git a/g10/g10.c b/g10/g10.c
index 4fbc0f7ab..fae08fc33 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -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 <[email protected]>."
+ ); 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 26:
- p = _("Please report bugs to <[email protected]>.\n");
+ 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 31: p = "\n"; break;
+ case 32:
+ if( !ciphers )
+ ciphers = build_list("Supported ciphers: ", cipher_algo_to_string,
+ check_cipher_algo );
+ p = ciphers;
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
+ 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;
+
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);
diff --git a/g10/g10maint.c b/g10/g10maint.c
index bc64eb04d..618acc8fa 100644
--- a/g10/g10maint.c
+++ b/g10/g10maint.c
@@ -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 <[email protected]>."
+ ); 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 26:
- p = _("Please report bugs to <[email protected]>.\n");
+ 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 31: p = "\n"; break;
+ case 32:
+ if( !ciphers )
+ ciphers = build_list("Supported ciphers: ", cipher_algo_to_string,
+ check_cipher_algo );
+ p = ciphers;
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
+ 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;
+
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);
diff --git a/g10/getkey.c b/g10/getkey.c
index 7182f4d4f..8f92f0a45 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -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:
diff --git a/g10/import.c b/g10/import.c
index 0474152d7..ce2655bfb 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -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 )
+{
+ 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 )
{
- log_fatal("Not yet implemented");
+ 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;
+}
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 83ec50742..c28748b6e 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -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;
+}
+
diff --git a/g10/keydb.h b/g10/keydb.h
index ca54020cd..643632a40 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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 );
diff --git a/g10/keygen.c b/g10/keygen.c
index 1c9a2efbe..89fd852e1 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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 );
diff --git a/g10/main.h b/g10/main.h
index 0c59de222..8761a1c59 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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*/
diff --git a/g10/mainproc.c b/g10/mainproc.c
index a7c17f9c8..7e19f12c1 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -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;
+ }
}
}
diff --git a/g10/revoke.c b/g10/revoke.c
new file mode 100644
index 000000000..2a8c5fc5c
--- /dev/null
+++ b/g10/revoke.c
@@ -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;
+}
+
+
diff --git a/g10/ringedit.c b/g10/ringedit.c
index adba3db0b..6d3fc14bb 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -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 */
diff --git a/g10/seskey.c b/g10/seskey.c
index 1488620cd..f157032d5 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -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:
*
diff --git a/g10/sig-check.c b/g10/sig-check.c
index dac3f4b74..4615c46e0 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -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 {
diff --git a/g10/sign.c b/g10/sign.c
index d6777442a..6040f4caf 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -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;