summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>1998-05-26 15:38:00 +0200
committerWerner Koch <wk@gnupg.org>1998-05-26 15:38:00 +0200
commiteed2faab53f859c98bf85f1e324614da640bf3ff (patch)
tree4a701250cb3300121456599f90cd7a22e03e8b59 /g10
parentnew release (diff)
downloadgnupg2-eed2faab53f859c98bf85f1e324614da640bf3ff.tar.xz
gnupg2-eed2faab53f859c98bf85f1e324614da640bf3ff.zip
add-key works
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog32
-rw-r--r--g10/armor.c9
-rw-r--r--g10/build-packet.c2
-rw-r--r--g10/compress.c6
-rw-r--r--g10/encode.c24
-rw-r--r--g10/g10.c5
-rw-r--r--g10/gpgd.c7
-rw-r--r--g10/import.c25
-rw-r--r--g10/keydb.h2
-rw-r--r--g10/keyedit.c63
-rw-r--r--g10/keygen.c387
-rw-r--r--g10/ks-proto.c246
-rw-r--r--g10/packet.h3
-rw-r--r--g10/passphrase.c43
-rw-r--r--g10/plaintext.c3
-rw-r--r--g10/revoke.c2
-rw-r--r--g10/seckey-cert.c12
-rw-r--r--g10/sign.c12
18 files changed, 756 insertions, 127 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 2838c7c8a..c320110c9 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,35 @@
+Tue May 26 11:24:33 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * passphrase.c (get_last_passphrase): New
+ (set_next_passphrase): New.
+ (passphrase_to_dek): add support for the above functions.
+ * keyedit.c (make_keysig_packet): Add sigclass 0x18,
+ changed all callers due to a new argument.
+ * keygen.c (write_keybinding): New
+ (generate_subkeypair): Add functionality
+ (ask_algo, ask_keysize, ask_valid_days): Broke out of generate_keypair
+ (ask_user_id, ask_passphrase): Ditto.
+
+Thu May 21 11:26:13 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * g10.c,gpgd.c (main): Does now return an int, so that egcs does
+ not complain.
+
+ * armor.c (fake_packet): Removed erro message and add a noticed
+ that this part should be fixed.
+
+ * sign.c (sign_file): Compression now comes in front of encryption.
+ * encode.c (encode_simple): Ditto.
+ (encode_crypt): Ditto.
+
+Tue May 19 16:18:19 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * armor.c (fake_packet): Changed assertion to log_error
+
+Sat May 16 16:02:06 1998 Werner Koch (wk@isil.d.shuttle.de)
+
+ * build-packet.c (build_packet): Add SUBKEY packets.
+
Fri May 15 17:57:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* sign.c (hash_for): New and used in all places here.
diff --git a/g10/armor.c b/g10/armor.c
index 462dc17b3..49352a1eb 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -703,8 +703,13 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
break;
case fhdrENDClearsig:
- assert( emplines );
- emplines--; /* don't count the last one */
+ /* FIXME: this is wrong: Only the last CRLF should
+ * not be included in the hash, muts rewrite the FSM again
+ * This proble does only occur if the last line does not end
+ * in with a LF?
+ */
+ if( emplines )
+ emplines--; /* don't count the last one */
state = fhdrENDClearsigHelp;
afx->helplen = n;
break;
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 1d4e05871..a37aba55c 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -82,9 +82,11 @@ build_packet( IOBUF out, PACKET *pkt )
case PKT_COMMENT:
rc = do_comment( out, ctb, pkt->pkt.comment );
break;
+ case PKT_PUBKEY_SUBCERT:
case PKT_PUBLIC_CERT:
rc = do_public_cert( out, ctb, pkt->pkt.public_cert );
break;
+ case PKT_SECKEY_SUBCERT:
case PKT_SECRET_CERT:
rc = do_secret_cert( out, ctb, pkt->pkt.secret_cert );
break;
diff --git a/g10/compress.c b/g10/compress.c
index 4e4d438e0..ca5adaebd 100644
--- a/g10/compress.c
+++ b/g10/compress.c
@@ -75,6 +75,9 @@ do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
do {
zs->next_out = zfx->outbuf;
zs->avail_out = zfx->outbufsize;
+ if( DBG_FILTER )
+ log_debug("call deflate: avail_in=%u, avail_out=%u\n",
+ (unsigned)zs->avail_in, (unsigned)zs->avail_out);
zrc = deflate( zs, flush );
if( zrc == Z_STREAM_END && flush == Z_FINISH )
;
@@ -145,6 +148,9 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
}
zs->avail_in = n;
}
+ if( DBG_FILTER )
+ log_debug("call inflate: avail_in=%u, avail_out=%u\n",
+ (unsigned)zs->avail_in, (unsigned)zs->avail_out);
zrc = inflate( zs, Z_PARTIAL_FLUSH );
if( DBG_FILTER )
log_debug("inflate returned: avail_in=%u, avail_out=%u, zrc=%d\n",
diff --git a/g10/encode.c b/g10/encode.c
index 1e37dfd74..142ffeac2 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -112,13 +112,10 @@ encode_simple( const char *filename, int mode )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
-
- write_comment( out, "#created by GNUPG v" VERSION " ("
+ else
+ write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
- if( opt.compress )
- iobuf_push_filter( out, compress_filter, &zfx );
-
if( s2k ) {
PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
enc->version = 4;
@@ -150,11 +147,14 @@ encode_simple( const char *filename, int mode )
pt->buf = inp;
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = pt;
- cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;
+ cfx.datalen = filesize && !opt.compress ? calc_packet_length( &pkt ) : 0;
/* register the cipher filter */
if( mode )
iobuf_push_filter( out, cipher_filter, &cfx );
+ /* register the compress filter */
+ if( opt.compress )
+ iobuf_push_filter( out, compress_filter, &zfx );
/* do the work */
if( (rc = build_packet( out, &pkt )) )
@@ -211,13 +211,10 @@ encode_crypt( const char *filename, STRLIST remusr )
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
-
- write_comment( out, "#created by GNUPG v" VERSION " ("
+ else
+ write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
- if( opt.compress )
- iobuf_push_filter( out, compress_filter, &zfx );
-
/* create a session key */
cfx.dek = m_alloc_secure( sizeof *cfx.dek );
cfx.dek->algo = opt.def_cipher_algo;
@@ -249,10 +246,13 @@ encode_crypt( const char *filename, STRLIST remusr )
init_packet(&pkt);
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = pt;
- cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;
+ cfx.datalen = filesize && !opt.compress? calc_packet_length( &pkt ) : 0;
/* register the cipher filter */
iobuf_push_filter( out, cipher_filter, &cfx );
+ /* register the compress filter */
+ if( opt.compress )
+ iobuf_push_filter( out, compress_filter, &zfx );
/* do the work */
if( (rc = build_packet( out, &pkt )) )
diff --git a/g10/g10.c b/g10/g10.c
index cc91d1ac4..322a9f3b9 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -201,7 +201,7 @@ strusage( int level )
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
- _("Please report bugs to <gnupg-bugs@isil.d.shuttle.de>.\n");
+ _("Please report bugs to <gnupg-bugs@gnu.org>.\n");
break;
case 1:
case 40: p =
@@ -364,7 +364,7 @@ check_opts(void)
-void
+int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
@@ -1005,6 +1005,7 @@ main( int argc, char **argv )
FREE_STRLIST(remusr);
FREE_STRLIST(locusr);
g10_exit(0);
+ return 8; /*NEVER REACHED*/
}
diff --git a/g10/gpgd.c b/g10/gpgd.c
index 010b319b9..72fcade8d 100644
--- a/g10/gpgd.c
+++ b/g10/gpgd.c
@@ -58,7 +58,7 @@ strusage( int level )
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
- "Please report bugs to <gnupg-bugs@isil.d.shuttle.de>.\n";
+ "Please report bugs to <gnupg-bugs@gnu.org>.\n";
break;
case 1:
case 40: p = "Usage: gpgd [options] (-h for help)";
@@ -135,7 +135,7 @@ set_debug(void)
}
-void
+int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
@@ -236,9 +236,8 @@ main( int argc, char **argv )
become_daemon();
-
-
g10_exit(0);
+ return 8; /*NEVER REACHED*/
}
diff --git a/g10/import.c b/g10/import.c
index 68ecd5330..228c754eb 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -43,7 +43,8 @@ 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 );
static int merge_blocks( const char *fname, KBNODE keyblock_orig,
- KBNODE keyblock, u32 *keyid, int *n_uids, int *n_sigs );
+ KBNODE keyblock, u32 *keyid,
+ int *n_uids, int *n_sigs, int *n_subk );
static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs,
const char *fname, u32 *keyid );
static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
@@ -103,7 +104,7 @@ import_pubkeys( const char *fname )
return G10ERR_OPEN_FILE;
}
- if( !opt.no_armor ) /* armored reading is not diabled */
+ if( !opt.no_armor ) /* armored reading is not disabled */
iobuf_push_filter( inp, armor_filter, &afx );
while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) {
@@ -305,7 +306,7 @@ import_one( const char *fname, KBNODE keyblock )
log_info("%s: key %08lX imported\n", fname, (ulong)keyid[1]);
}
else { /* merge */
- int n_uids, n_sigs;
+ int n_uids, n_sigs, n_subk;
/* Compare the original against the new key; just to be sure nothing
* weird is going on */
@@ -335,12 +336,13 @@ import_one( const char *fname, KBNODE keyblock )
/* and try to merge the block */
clear_kbnode_flags( keyblock_orig );
clear_kbnode_flags( keyblock );
- n_uids = n_sigs = 0;
+ n_uids = n_sigs = n_subk = 0;
rc = merge_blocks( fname, keyblock_orig, keyblock,
- keyid, &n_uids, &n_sigs );
+ keyid, &n_uids, &n_sigs, &n_subk );
if( rc )
goto leave;
- if( n_uids || n_sigs ) { /* keyblock_orig has been updated; write */
+ if( n_uids || n_sigs || n_subk ) {
+ /* keyblock_orig has been updated; write */
if( opt.verbose > 1 )
log_info("%s: writing to '%s'\n",
fname, keyblock_resource_name(&kbpos) );
@@ -364,6 +366,12 @@ import_one( const char *fname, KBNODE keyblock )
else if( n_sigs )
log_info("%s: key %08lX, %d new signatures\n",
fname, (ulong)keyid[1], n_sigs );
+ if( n_subk == 1 )
+ log_info("%s: key %08lX, 1 new subkey\n",
+ fname, (ulong)keyid[1]);
+ else if( n_subk )
+ log_info("%s: key %08lX, %d new subkeys\n",
+ fname, (ulong)keyid[1], n_subk );
}
else
log_info("%s: key %08lX, not changed\n", fname, (ulong)keyid[1] );
@@ -593,7 +601,7 @@ delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
*/
static int
merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
- u32 *keyid, int *n_uids, int *n_sigs )
+ u32 *keyid, int *n_uids, int *n_sigs, int *n_subk )
{
KBNODE onode, node;
int rc, found;
@@ -667,6 +675,9 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
}
}
+ /* 4th: add new subkeys */
+ /* FIXME */
+
return 0;
}
diff --git a/g10/keydb.h b/g10/keydb.h
index 968ee692a..3df11771e 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -98,6 +98,8 @@ int build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list,
void set_passphrase_fd( int fd );
int get_passphrase_fd(void);
DEK *passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode);
+void set_next_passphrase( const char *s );
+char *get_last_passphrase(void);
/*-- getkey.c --*/
void add_keyring( const char *name );
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 77da1977b..f5c95ea32 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -169,10 +169,6 @@ remove_keysigs( KBNODE keyblock, u32 *keyid, int all )
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
PKT_signature *sig = node->pkt->pkt.signature;
- if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
- /* fixme: skip self-sig */
- }
-
tty_printf("\n \"%08lX %s ",
sig->keyid[1], datestr_from_sig(sig));
if( node->flag & 6 )
@@ -349,6 +345,7 @@ sign_key( const char *username, STRLIST locusr )
rc = make_keysig_packet( &sig, pkc,
node->pkt->pkt.user_id,
+ NULL,
skc_rover->skc,
0x10, 0 );
if( rc ) {
@@ -568,9 +565,10 @@ change_passphrase( const char *username )
KBNODE node;
KBPOS kbpos;
PKT_secret_cert *skc;
- u32 skc_keyid[2];
+ u32 keyid[2];
char *answer;
int changed=0;
+ char *passphrase = NULL;
/* find the userid */
rc = find_secret_keyblock_byname( &kbpos, username );
@@ -595,18 +593,28 @@ change_passphrase( const char *username )
}
skc = node->pkt->pkt.secret_cert;
- keyid_from_skc( skc, skc_keyid );
+ keyid_from_skc( skc, keyid );
tty_printf("sec %4u%c/%08lX %s ",
nbits_from_skc( skc ),
pubkey_letter( skc->pubkey_algo ),
- skc_keyid[1], datestr_from_skc(skc) );
+ keyid[1], datestr_from_skc(skc) );
{
size_t n;
- char *p = get_user_id( skc_keyid, &n );
+ char *p = get_user_id( keyid, &n );
tty_print_string( p, n );
m_free(p);
tty_printf("\n");
}
+ for(node=keyblock; node; node = node->next ) {
+ if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) {
+ PKT_secret_cert *subskc = node->pkt->pkt.secret_cert;
+ keyid_from_skc( subskc, keyid );
+ tty_printf("sub %4u%c/%08lX %s\n",
+ nbits_from_skc( subskc ),
+ pubkey_letter( subskc->pubkey_algo ),
+ keyid[1], datestr_from_skc(subskc) );
+ }
+ }
clear_kbnode_flags( keyblock );
switch( is_secret_key_protected( skc ) ) {
@@ -619,10 +627,21 @@ change_passphrase( const char *username )
default:
tty_printf("Key is protected.\n");
rc = check_secret_key( skc );
+ if( !rc )
+ passphrase = get_last_passphrase();
break;
}
- /* fixme: unprotect all subkeys */
+ /* unprotect all subkeys (use the supplied passphrase or ask)*/
+ for(node=keyblock; node; node = node->next ) {
+ if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) {
+ PKT_secret_cert *subskc = node->pkt->pkt.secret_cert;
+ set_next_passphrase( passphrase );
+ rc = check_secret_key( subskc );
+ if( rc )
+ break;
+ }
+ }
if( rc )
tty_printf("Can't edit this key: %s\n", g10_errstr(rc));
@@ -632,6 +651,7 @@ change_passphrase( const char *username )
tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
+ set_next_passphrase( NULL );
for(;;) {
s2k->mode = 1;
s2k->hash_algo = DIGEST_ALGO_RMD160;
@@ -651,10 +671,17 @@ change_passphrase( const char *username )
break;
}
else { /* okay */
- /* fixme: protect all subkeys too */
skc->protect.algo = dek->algo;
skc->protect.s2k = *s2k;
rc = protect_secret_key( skc, dek );
+ for(node=keyblock; !rc && node; node = node->next ) {
+ if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) {
+ PKT_secret_cert *subskc = node->pkt->pkt.secret_cert;
+ subskc->protect.algo = dek->algo;
+ subskc->protect.s2k = *s2k;
+ rc = protect_secret_key( subskc, dek );
+ }
+ }
if( rc )
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
else
@@ -676,7 +703,9 @@ change_passphrase( const char *username )
}
leave:
+ m_free( passphrase );
release_kbnode( keyblock );
+ set_next_passphrase( NULL );
return rc;
}
@@ -689,14 +718,16 @@ change_passphrase( const char *username )
*/
int
make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
- PKT_user_id *uid, PKT_secret_cert *skc,
+ PKT_user_id *uid, PKT_public_cert *subpkc,
+ PKT_secret_cert *skc,
int sigclass, int digest_algo )
{
PKT_signature *sig;
int rc=0;
MD_HANDLE md;
- assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x20 );
+ assert( (sigclass >= 0x10 && sigclass <= 0x13)
+ || sigclass == 0x20 || sigclass == 0x18 );
if( !digest_algo ) {
switch( skc->pubkey_algo ) {
case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break;
@@ -706,11 +737,13 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
}
}
md = md_open( digest_algo, 0 );
- /*md_start_debug( md, "make" );*/
/* hash the public key certificate and the user id */
hash_public_cert( md, pkc );
- if( sigclass != 0x20 ) {
+ if( sigclass == 0x18 ) { /* subkey binding */
+ hash_public_cert( md, subpkc );
+ }
+ else if( sigclass != 0x20 ) {
if( skc->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
@@ -759,7 +792,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
- buf[2] = n >> 24; /* hmmm, n is only 16 bit, so tthis is always 0 */
+ buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
diff --git a/g10/keygen.c b/g10/keygen.c
index b6894ab79..367c22de5 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -79,7 +79,47 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
pkc = node->pkt->pkt.public_cert;
/* and make the signature */
- rc = make_keysig_packet( &sig, pkc, uid, skc, 0x13, 0 );
+ rc = make_keysig_packet( &sig, pkc, uid, NULL, skc, 0x13, 0 );
+ if( rc ) {
+ log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
+ return rc;
+ }
+
+ pkt = m_alloc_clear( sizeof *pkt );
+ pkt->pkttype = PKT_SIGNATURE;
+ pkt->pkt.signature = sig;
+ add_kbnode( root, new_kbnode( pkt ) );
+ return rc;
+}
+
+static int
+write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
+{
+ PACKET *pkt;
+ PKT_signature *sig;
+ int rc=0;
+ KBNODE node;
+ PKT_public_cert *pkc, *subpkc;
+
+ if( opt.verbose )
+ log_info(_("writing key binding signature\n"));
+
+ /* get the pkc packet from the pub_tree */
+ node = find_kbnode( pub_root, PKT_PUBLIC_CERT );
+ if( !node )
+ BUG();
+ pkc = node->pkt->pkt.public_cert;
+ /* find the last subkey */
+ subpkc = NULL;
+ for(node=pub_root; node; node = node->next ) {
+ if( node->pkt->pkttype == PKT_PUBKEY_SUBCERT )
+ subpkc = node->pkt->pkt.public_cert;
+ }
+ if( !subpkc )
+ BUG();
+
+ /* and make the signature */
+ rc = make_keysig_packet( &sig, pkc, NULL, subpkc, skc, 0x18, 0 );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
@@ -95,7 +135,8 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
static int
gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
- STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
+ STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days,
+ int version )
{
int rc;
int i;
@@ -111,6 +152,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc = m_alloc_clear( sizeof *skc );
pkc = m_alloc_clear( sizeof *pkc );
skc->timestamp = pkc->timestamp = make_timestamp();
+ skc->version = pkc->version = version;
skc->valid_days = pkc->valid_days = valid_days;
skc->pubkey_algo = pkc->pubkey_algo = PUBKEY_ALGO_ELGAMAL;
pkc->d.elg.p = pk.p;
@@ -124,8 +166,8 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->protect.algo = 0;
skc->csum = checksum_mpi( skc->d.elg.x );
- /* return an unprotected version of the skc */
- *ret_skc = copy_secret_cert( NULL, skc );
+ if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
+ *ret_skc = copy_secret_cert( NULL, skc );
if( dek ) {
skc->protect.algo = dek->algo;
@@ -140,14 +182,14 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
}
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_PUBLIC_CERT;
+ pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT;
pkt->pkt.public_cert = pkc;
add_kbnode(pub_root, new_kbnode( pkt ));
/* don't know whether it makes sense to have the factors, so for now
* we store them in the secret keyring (but they are not secret) */
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_SECRET_CERT;
+ pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT;
pkt->pkt.secret_cert = skc;
add_kbnode(sec_root, new_kbnode( pkt ));
for(i=0; factors[i]; i++ )
@@ -192,8 +234,8 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_q );
skc->d.rsa.csum += checksum_mpi( skc->d.rsa.rsa_u );
- /* return an unprotected version of the skc */
- *ret_skc = copy_secret_cert( NULL, skc );
+ if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
+ *ret_skc = copy_secret_cert( NULL, skc );
if( dek ) {
skc->d.rsa.is_protected = 1;
@@ -210,12 +252,12 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
}
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_PUBLIC_CERT;
+ pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT;
pkt->pkt.public_cert = pkc;
add_kbnode(pub_root, new_kbnode( pkt ));
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_SECRET_CERT;
+ pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT;
pkt->pkt.secret_cert = skc;
add_kbnode(sec_root, new_kbnode( pkt ));
@@ -267,8 +309,8 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
skc->protect.algo = 0;
skc->csum = checksum_mpi( skc->d.dsa.x );
- /* return an unprotected version of the skc */
- *ret_skc = copy_secret_cert( NULL, skc );
+ if( ret_skc ) /* not a subkey: return an unprotected version of the skc */
+ *ret_skc = copy_secret_cert( NULL, skc );
if( dek ) {
skc->protect.algo = dek->algo;
@@ -283,7 +325,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
}
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_PUBLIC_CERT;
+ pkt->pkttype = ret_skc ? PKT_PUBLIC_CERT : PKT_PUBKEY_SUBCERT;
pkt->pkt.public_cert = pkc;
add_kbnode(pub_root, new_kbnode( pkt ));
@@ -294,7 +336,7 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
* are known.
*/
pkt = m_alloc_clear(sizeof *pkt);
- pkt->pkttype = PKT_SECRET_CERT;
+ pkt->pkttype = ret_skc ? PKT_SECRET_CERT : PKT_SECKEY_SUBCERT;
pkt->pkt.secret_cert = skc;
add_kbnode(sec_root, new_kbnode( pkt ));
for(i=1; factors[i]; i++ ) /* the first one is q */
@@ -334,74 +376,63 @@ check_valid_days( const char *s )
}
-/****************
- * Generate a keypair
- */
-void
-generate_keypair()
+static int
+ask_algo( int *ret_v4 )
{
char *answer;
- unsigned nbits;
- char *pub_fname = NULL;
- char *sec_fname = NULL;
- char *uid = NULL;
- KBNODE pub_root = NULL;
- KBNODE sec_root = NULL;
- PKT_secret_cert *skc = NULL;
- DEK *dek = NULL;
- STRING2KEY *s2k;
- int rc;
int algo;
- const char *algo_name;
- char *aname, *acomment, *amail;
- int valid_days=0;
-
- if( opt.batch || opt.answer_yes || opt.answer_no ) {
- log_error(_("Key generation can only be used in interactive mode\n"));
- return;
- }
tty_printf(_("Please select the algorithm to use:\n"
" (1) ElGamal is the suggested one.\n"
- " (2) DSA can only be used for signatures.\n"));
+ " (2) ElGamal using v4 packets (OpenPGP)\n"
+ " (3) DSA can only be used for signatures.\n"));
#ifdef ENABLE_RSA_KEYGEN
- tty_printf(_(" (3) RSA cannot be used in the U.S.\n"));
+ tty_printf(_(" (4) RSA cannot be used in the U.S.\n"));
#endif
+ *ret_v4 = 0;
for(;;) {
#ifdef ENABLE_RSA_KEYGEN
- answer = tty_get(_("Your selection? (1,2,3) "));
+ answer = tty_get(_("Your selection? (1,2,3,4) "));
#else
- answer = tty_get(_("Your selection? (1,2) "));
+ answer = tty_get(_("Your selection? (1,2,3) "));
#endif
tty_kill_prompt();
algo = *answer? atoi(answer): 1;
m_free(answer);
- if( algo == 1 ) {
+ if( algo == 1 || algo == 2 ) {
+ if( algo == 2 )
+ *ret_v4 = 1;
algo = PUBKEY_ALGO_ELGAMAL;
- algo_name = "ElGamal";
break;
}
- else if( algo == 2 ) {
+ else if( algo == 3 ) {
+ *ret_v4 = 1;
algo = PUBKEY_ALGO_DSA;
- algo_name = "DSA";
break;
}
#ifdef ENABLE_RSA_KEYGEN
- else if( algo == 3 ) {
+ else if( algo == 4 ) {
algo = PUBKEY_ALGO_RSA;
- algo_name = "RSA";
break;
}
#endif
}
+ return algo;
+}
+static unsigned
+ask_keysize( int algo )
+{
+ char *answer;
+ unsigned nbits;
tty_printf(_("About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
- " highest suggested keysize is 2048 bits\n"), algo_name );
+ " highest suggested keysize is 2048 bits\n"),
+ pubkey_algo_to_string(algo) );
for(;;) {
answer = tty_get(_("What keysize do you want? (1024) "));
tty_kill_prompt();
@@ -446,6 +477,15 @@ generate_keypair()
nbits = ((nbits + 31) / 32) * 32;
tty_printf(_("rounded up to %u bits\n"), nbits );
}
+ return nbits;
+}
+
+
+static int
+ask_valid_days()
+{
+ char *answer;
+ int valid_days=0;
tty_printf(_("Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
@@ -491,15 +531,21 @@ generate_keypair()
break;
}
m_free(answer);
+ return valid_days;
+}
+static char *
+ask_user_id()
+{
+ char *answer;
+ char *aname, *acomment, *amail, *uid;
tty_printf( _("\n"
"You need a User-ID to identify your key; the software constructs the user id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
- uid = NULL;
- aname=acomment=amail=NULL;
+ uid = aname = acomment = amail = NULL;
for(;;) {
char *p;
@@ -600,7 +646,15 @@ generate_keypair()
break;
m_free(uid); uid = NULL;
}
+ return uid;
+}
+
+static DEK *
+ask_passphrase( STRING2KEY **ret_s2k )
+{
+ DEK *dek = NULL;
+ STRING2KEY *s2k;
tty_printf(_("You need a Passphrase to protect your secret key.\n\n") );
@@ -624,23 +678,17 @@ generate_keypair()
else
break; /* okay */
}
+ *ret_s2k = s2k;
+ return dek;
+}
- /* now check whether we are allowed to write to the keyrings */
- pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
- sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
- if( opt.verbose ) {
- tty_printf(_("writing public certificate to '%s'\n"), pub_fname );
- tty_printf(_("writing secret certificate to '%s'\n"), sec_fname );
- }
-
- /* we create the packets as a tree of kbnodes. Because the structure
- * we create is known in advance we simply generate a linked list
- * 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);
- sec_root = make_comment_node("#"); delete_kbnode(sec_root);
+static int
+do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
+ DEK *dek, STRING2KEY *s2k, PKT_secret_cert **skc, int valid_days,
+ int v4_packet )
+{
+ int rc=0;
tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
@@ -649,13 +697,14 @@ generate_keypair()
"number generator a better chance to gain enough entropy.\n") );
if( algo == PUBKEY_ALGO_ELGAMAL )
- rc = gen_elg(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days );
+ rc = gen_elg(nbits, pub_root, sec_root, dek, s2k,
+ skc, valid_days, v4_packet? 4:3 );
#ifdef ENABLE_RSA_KEYGEN
else if( algo == PUBKEY_ALGO_RSA )
- rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days );
+ rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days );
#endif
else if( algo == PUBKEY_ALGO_DSA )
- rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days);
+ rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, skc, valid_days);
else
BUG();
if( !rc ) {
@@ -666,6 +715,59 @@ generate_keypair()
make_comment_node("#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")"));
}
+ return rc;
+}
+
+
+/****************
+ * Generate a keypair
+ */
+void
+generate_keypair()
+{
+ unsigned nbits;
+ char *pub_fname = NULL;
+ char *sec_fname = NULL;
+ char *uid = NULL;
+ KBNODE pub_root = NULL;
+ KBNODE sec_root = NULL;
+ PKT_secret_cert *skc = NULL;
+ DEK *dek;
+ STRING2KEY *s2k;
+ int rc;
+ int algo;
+ int ndays;
+ int v4;
+
+ if( opt.batch || opt.answer_yes || opt.answer_no ) {
+ log_error(_("Key generation can only be used in interactive mode\n"));
+ return;
+ }
+
+ algo = ask_algo( &v4 );
+ nbits = ask_keysize( algo );
+ ndays = ask_valid_days();
+ uid = ask_user_id();
+ dek = ask_passphrase( &s2k );
+
+
+ /* now check whether we are allowed to write to the keyrings */
+ pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
+ sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
+ if( opt.verbose ) {
+ tty_printf(_("writing public certificate to '%s'\n"), pub_fname );
+ tty_printf(_("writing secret certificate to '%s'\n"), sec_fname );
+ }
+
+ /* we create the packets as a tree of kbnodes. Because the structure
+ * we create is known in advance we simply generate a linked list
+ * 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);
+ sec_root = make_comment_node("#"); delete_kbnode(sec_root);
+
+ rc = do_create( algo, nbits, pub_root, sec_root, dek, s2k, &skc, ndays, v4);
if( !rc )
write_uid(pub_root, uid );
if( !rc )
@@ -718,6 +820,11 @@ generate_keypair()
log_error("can't write secret key: %s\n", g10_errstr(rc) );
else {
tty_printf(_("public and secret key created and signed.\n") );
+ if( algo == PUBKEY_ALGO_DSA )
+ tty_printf(_("Note that this key cannot be used for "
+ "encryption. You may want to use\n"
+ "the command \"--add-key\" to generate a "
+ "secondary key for this purpose.\n") );
}
if( !rc1 )
@@ -745,8 +852,148 @@ generate_keypair()
* add a new subkey to an existing key.
*/
void
-generate_subkeypair( const char *userid )
+generate_subkeypair( const char *username )
{
- log_fatal("To be implemented :-)\n");
+ int rc=0;
+ KBPOS pub_kbpos, sec_kbpos;
+ KBNODE pub_keyblock = NULL;
+ KBNODE sec_keyblock = NULL;
+ KBNODE node;
+ PKT_secret_cert *skc = NULL; /* this is the primary skc */
+ u32 keyid[2];
+ int v4, algo, ndays;
+ unsigned nbits;
+ char *passphrase = NULL;
+ DEK *dek = NULL;
+ STRING2KEY *s2k = NULL;
+
+ if( opt.batch || opt.answer_yes || opt.answer_no ) {
+ log_error(_("Key generation can only be used in interactive mode\n"));
+ return;
+ }
+
+ /* search the userid */
+ rc = find_secret_keyblock_byname( &sec_kbpos, username );
+ if( rc ) {
+ log_error("user '%s' not found\n", username );
+ goto leave;
+ }
+ rc = read_keyblock( &sec_kbpos, &sec_keyblock );
+ if( rc ) {
+ log_error("error reading the secret key: %s\n", g10_errstr(rc) );
+ goto leave;
+ }
+ /* and the public key */
+ rc = find_keyblock_byname( &pub_kbpos, username );
+ if( rc ) {
+ log_error("user '%s' not found in public ring\n", username );
+ goto leave;
+ }
+ rc = read_keyblock( &pub_kbpos, &pub_keyblock );
+ if( rc ) {
+ log_error("error reading the public key: %s\n", g10_errstr(rc) );
+ goto leave;
+ }
+
+ /* break out the primary key */
+ node = find_kbnode( sec_keyblock, PKT_SECRET_CERT );
+ if( !node ) {
+ log_error("Oops; secret key not found anymore!\n");
+ rc = G10ERR_GENERAL;
+ goto leave;
+ }
+
+ /* make a copy of the skc to keep the protected one in the keyblock */
+ skc = copy_secret_cert( NULL, node->pkt->pkt.secret_cert );
+ keyid_from_skc( skc, keyid );
+ /* display primary and all secondary keys */
+ tty_printf("sec %4u%c/%08lX %s ",
+ nbits_from_skc( skc ),
+ pubkey_letter( skc->pubkey_algo ),
+ keyid[1], datestr_from_skc(skc) );
+ {
+ size_t n;
+ char *p = get_user_id( keyid, &n );
+ tty_print_string( p, n );
+ m_free(p);
+ tty_printf("\n");
+ }
+ for(node=sec_keyblock; node; node = node->next ) {
+ if( node->pkt->pkttype == PKT_SECKEY_SUBCERT ) {
+ PKT_secret_cert *subskc = node->pkt->pkt.secret_cert;
+ keyid_from_skc( subskc, keyid );
+ tty_printf("sub %4u%c/%08lX %s\n",
+ nbits_from_skc( subskc ),
+ pubkey_letter( subskc->pubkey_algo ),
+ keyid[1], datestr_from_skc(subskc) );
+ }
+ }
+ tty_printf("\n");
+
+
+
+ /* unprotect to get the passphrase */
+ switch( is_secret_key_protected( skc ) ) {
+ case -1:
+ rc = G10ERR_PUBKEY_ALGO;
+ break;
+ case 0:
+ tty_printf("This key is not protected.\n");
+ break;
+ default:
+ tty_printf("Key is protected.\n");
+ rc = check_secret_key( skc );
+ if( !rc )
+ passphrase = get_last_passphrase();
+ break;
+ }
+ if( rc )
+ goto leave;
+
+
+ algo = ask_algo( &v4 );
+ nbits = ask_keysize( algo );
+ ndays = ask_valid_days();
+
+ if( passphrase ) {
+ s2k = m_alloc_secure( sizeof *s2k );
+ s2k->mode = 1;
+ s2k->hash_algo = DIGEST_ALGO_RMD160;
+ set_next_passphrase( passphrase );
+ dek = passphrase_to_dek( NULL, CIPHER_ALGO_BLOWFISH, s2k, 2 );
+ }
+
+ rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
+ dek, s2k, NULL, ndays, v4 );
+ if( !rc )
+ rc = write_keybinding(pub_keyblock, pub_keyblock, skc);
+ if( !rc )
+ rc = write_keybinding(sec_keyblock, pub_keyblock, skc);
+ /* write back */
+ if( !rc ) {
+ rc = update_keyblock( &pub_kbpos, pub_keyblock );
+ if( rc )
+ log_error("update_public_keyblock failed\n" );
+ }
+ if( !rc ) {
+ rc = update_keyblock( &sec_kbpos, sec_keyblock );
+ if( rc )
+ log_error("update_secret_keyblock failed\n" );
+ }
+ if( !rc )
+ tty_printf(_("public and secret subkey created.\n") );
+
+
+ leave:
+ if( rc )
+ tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
+ m_free( passphrase );
+ m_free( dek );
+ m_free( s2k );
+ if( skc ) /* release the copy of the (now unprotected) secret key */
+ free_secret_cert(skc);
+ release_kbnode( sec_keyblock );
+ release_kbnode( pub_keyblock );
+ set_next_passphrase( NULL );
}
diff --git a/g10/ks-proto.c b/g10/ks-proto.c
index 38f21762b..b862357fb 100644
--- a/g10/ks-proto.c
+++ b/g10/ks-proto.c
@@ -18,6 +18,32 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
+/****************
+ * The extended HKP protocol:
+ *
+ * GET /pks/lookup[/<gnupg_user_id>][?[op=<cmd>][&armor=0][&search=<keywords>]]
+ *
+ * Default is: "armor=1", "op=get". "search" is only allowed if gnupg_user_id
+ * is not present. GET maybe replaced by HEAD in which case only some status
+ * information is returned.
+ *
+ * Hmmm, I don't like it, the better solution is to use:
+ *
+ * /pks/gnupg/get for binary lookups
+ * /pks/gnupg/upd to update a key
+ * /pks/gnupg/ins to insert a new key
+ *
+ * Optional a version string can be inserted as in:
+ *
+ * /pks/gnupg/v1.0/get
+ *
+ * Returned HTTP options:
+ * X-Key-Hash: <rmd160 hash value of the keyblock>
+ * X-Key-MTime: <last modification time>
+ * X-Key-LID: <local_key_id_used_for_update_etc>
+ * [fixme: is X-.... allowed?]
+ */
+
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,6 +60,226 @@ read_line( FILE *fp )
{
return -1;
}
+
+
+
+
+/****************
+ * Send a HKP request
+ */
+int
+hkp_request( int operation, const char *user_id )
+{
+
+}
+
+
+
+
+
+/************************************************
+ ******* client communication stuff ************
+ ************************************************/
+
+/****************
+ * Initialisieren des clients
+ * Es wird ein Handle zurückgegeben oder -1 bei einem fehler.
+ * z.Z. ist nut eine Verbindung gleichzeitig möglich.
+ * Wenn einer serverpid von 0 angegeben wird, so wird diese
+ * der environment variabeln ATEXDB_PID entnommen.
+ */
+
+int
+hkp_open( const char *serverurl )
+{
+ const char *s;
+
+ s = SERVER_NAME_TEMPLATE;
+ client.serv_name = xmalloc(strlen(s) + 10 );
+ sprintf(client.serv_name,s, serverpid );
+ if( opt.verbose )
+ Info("Using unix domain stream '%s'", client.serv_name );
+
+ memset( &client.serv_addr, 0, sizeof client.serv_addr );
+ client.serv_addr.sun_family = AF_UNIX;
+ strcpy( client.serv_addr.sun_path, client.serv_name );
+ client.serv_addr_len = strlen(client.serv_addr.sun_path)
+ + sizeof client.serv_addr.sun_family;
+
+ client.sockfd = -1;
+ if( DoCheckVersion() )
+ return -1;
+ return 0;
+}
+
+
+static int
+DoConnect()
+{
+ if( client.sockfd != -1 )
+ DoDisconnect();
+ if( (client.sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {
+ Error(1000,"can't open unix domain socket");
+ return 1;
+ }
+ if( connect(client.sockfd, (struct sockaddr*)&client.serv_addr,
+ client.serv_addr_len) == -1 ) {
+ Error(1000,"can't connect to '%s'",client.serv_addr.sun_path);
+ return 1;
+ }
+
+ return 0; /* okay */
+}
+
+static int
+DoDisconnect()
+{
+ if( client.sockfd != -1 ) {
+ close(client.sockfd);
+ client.sockfd = -1;
+ }
+ return 0; /* okay */
+}
+
+/****************
+ * NBYTES auf den aktuellen stream schreiben.
+ */
+static int
+DoWrite( void *buf, size_t nbytes )
+{
+ size_t nleft = nbytes;
+ ssize_t nwritten;
+
+ while( nleft > 0 ) {
+ /* FIXME: add EINTR handling */
+ nwritten = write(client.sockfd, buf, nleft);
+ if( nwritten < 0 ) {
+ Error(1000,"error writing to server");
+ return -1;
+ }
+ nleft -= nwritten;
+ buf = (char*)buf + nwritten;
+ }
+ return 0;
+}
+
+static int
+DoWriteStr( const char *s )
+{
+ return DoWrite((char *)s, strlen(s) );
+}
+
+
+static int
+DoRead( void *buf, size_t buflen, size_t *ret_nread, int stop)
+{
+ size_t nleft = buflen;
+ int nread;
+ char *p;
+
+ p = buf;
+ while( nleft > 0 ) {
+ /* FIXME: add EINTR handling */
+ nread = read(client.sockfd, buf, stop? 1 : nleft);
+ if( nread < 0 ) {
+ Error(1000,"error reading from server");
+ return -1;
+ }
+ else if( !nread )
+ break; /* EOF */
+ nleft -= nread;
+ buf = (char*)buf + nread;
+ if( stop )
+ for(; p < (char*)buf ; p++ )
+ if( *p == '\n' )
+ goto leave;
+ }
+ leave:
+ if( ret_nread )
+ *ret_nread = buflen - nleft;
+ return 0;
+}
+
+/****************
+ * Like DoRead(), but append the received data to the given strgbuf.
+ * read a maximum of nbytes;
+ */
+static int
+DoReadIntoStrgbuf( strgbuf_t *strgbuf, size_t nbytes, size_t *ret_nread)
+{
+ size_t ntotal, nleft;
+ int nread;
+ byte *p, buffer[1000];
+
+ ntotal = 0;
+ nleft = nbytes;
+ while( nleft ) {
+ nread = read(client.sockfd, buffer,
+ nleft > DIM(buffer)? DIM(buffer) : nleft);
+ if( nread < 0 ) {
+ Error(1000,"error reading from server");
+ return -1;
+ }
+ else if( !nread )
+ break; /* EOF */
+ nleft -= nread;
+ ntotal += nread;
+ /* ab in den stringbuffer */
+ for(p=buffer; nread; nread--, p++ )
+ PutStrgbuf(strgbuf, *p );
+ }
+
+ if( ret_nread )
+ *ret_nread = ntotal;
+ return 0;
+}
+
+
+/****************
+ * In retval wird das numerische argument nach OK zurückgegeben
+ */
+static int
+DoRequest( char *request, long *retval )
+{
+ if( DoWrite(request, strlen(request)) )
+ return -1;
+ return DoWaitReply( retval );
+}
+
+static int
+DoWaitReply( long *retval )
+{
+ char *p, buf[200]; /* enough room for messages */
+ size_t nread;
+
+ /* read but stop at the first newline */
+ if( DoRead(buf, DIM(buf)-2, &nread, 1 ) )
+ return -1;
+ buf[DIM(buf)-1] = 0;
+ /* fixme: should check, that we have the linefeed and otherwise
+ * perform a dummy read */
+ if( p = strchr(buf, '\n') )
+ *p = 0;
+ if( *buf == 'O' && buf[1] == 'K' && (buf[2]==' ' || !buf[2]) ) {
+ if( retval )
+ *retval = buf[2]? strtol(buf+3, NULL, 10 ):0;
+ return 0;
+ }
+ Error(0, "Server replied: %.60s", buf );
+ return -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
#endif
diff --git a/g10/packet.h b/g10/packet.h
index 463cf53f2..7f38cd5cf 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -308,7 +308,8 @@ int write_comment( IOBUF out, const char *s );
/*-- sign.c --*/
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_cert *pkc,
- PKT_user_id *uid, PKT_secret_cert *skc,
+ PKT_user_id *uid, PKT_public_cert *subpkc,
+ PKT_secret_cert *skc,
int sigclass, int digest_algo );
#endif /*G10_PACKET_H*/
diff --git a/g10/passphrase.c b/g10/passphrase.c
index d3b882fa8..ebcba9942 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -33,6 +33,8 @@
#include "main.h"
static int pwfd = -1;
+static char *next_pw = NULL;
+static char *last_pw = NULL;
static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create );
@@ -48,6 +50,34 @@ get_passphrase_fd()
return pwfd;
}
+/****************
+ * Set the passphrase to be used for the next query and only for the next
+ * one.
+ */
+void
+set_next_passphrase( const char *s )
+{
+ m_free(next_pw);
+ next_pw = NULL;
+ if( s ) {
+ next_pw = m_alloc_secure( strlen(s)+1 );
+ strcpy(next_pw, s );
+ }
+}
+
+/****************
+ * Get the last passphrase used in passphrase_to_dek.
+ * Note: This removes the passphrase from this modules and
+ * the caller must free the result. May return NULL:
+ */
+char *
+get_last_passphrase()
+{
+ char *p = last_pw;
+ last_pw = NULL;
+ return p;
+}
+
/****************
* Get a passphrase for the secret key with KEYID, display TEXT
@@ -62,7 +92,7 @@ get_passphrase_fd()
DEK *
passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
{
- char *pw;
+ char *pw = NULL;
DEK *dek;
STRING2KEY help_s2k;
@@ -77,7 +107,7 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
:DEFAULT_DIGEST_ALGO;
}
- if( keyid && !opt.batch ) {
+ if( keyid && !opt.batch && !next_pw ) {
char *ustr;
tty_printf("Need a pass phrase to unlock the secret key for:\n");
tty_printf(" \"" );
@@ -87,7 +117,11 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
tty_printf("\"\n\n");
}
- if( pwfd != -1 ) { /* read the passphrase from the given descriptor */
+ if( next_pw ) {
+ pw = next_pw;
+ next_pw = NULL;
+ }
+ else if( pwfd != -1 ) { /* read the passphrase from the file */
int i, len;
if( !opt.batch )
@@ -130,7 +164,8 @@ passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
dek->keylen = 0;
else
hash_passphrase( dek, pw, s2k, mode==2 );
- m_free(pw); /* is allocated in secure memory, so it will be burned */
+ m_free(last_pw);
+ last_pw = pw;
return dek;
}
diff --git a/g10/plaintext.c b/g10/plaintext.c
index e15a269e8..cdf4fe2a2 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -77,7 +77,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx )
if( pt->len ) {
for( ; pt->len; pt->len-- ) {
if( (c = iobuf_get(pt->buf)) == -1 ) {
- log_error("Problem reading source\n");
+ log_error("Problem reading source (%u bytes remaining)\n",
+ (unsigned)pt->len);
rc = G10ERR_READ_FILE;
goto leave;
}
diff --git a/g10/revoke.c b/g10/revoke.c
index 68f51e810..cafe84de3 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -159,7 +159,7 @@ gen_revoke( const char *uname )
/* create it */
- rc = make_keysig_packet( &sig, pkc, NULL, skc, 0x20, 0);
+ rc = make_keysig_packet( &sig, pkc, NULL, NULL, skc, 0x20, 0);
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc));
goto leave;
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index a265a3713..8a5d98299 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -55,7 +55,7 @@ do_check( PKT_secret_cert *cert )
case CIPHER_ALGO_CAST:
keyid_from_skc( cert, keyid );
dek = passphrase_to_dek( keyid, cert->protect.algo,
- &cert->protect.s2k, 0 );
+ &cert->protect.s2k, 0 );
cipher_hd = cipher_open( cert->protect.algo,
CIPHER_MODE_AUTO_CFB, 1);
cipher_setkey( cipher_hd, dek->key, dek->keylen );
@@ -227,7 +227,7 @@ check_secret_key( PKT_secret_cert *cert )
case PUBKEY_ALGO_ELGAMAL:
case PUBKEY_ALGO_DSA:
rc = do_check( cert );
- #if 1 /* set to 0 to disable the workaround */
+ #if 0 /* set to 1 to enable the workaround */
if( rc == G10ERR_BAD_PASS && cert->is_protected
&& cert->protect.algo == CIPHER_ALGO_BLOWFISH
&& cert->pubkey_algo != PUBKEY_ALGO_ELGAMAL ) {
@@ -243,11 +243,19 @@ check_secret_key( PKT_secret_cert *cert )
}
#endif
break;
+ #ifdef HAVE_RSA_CIPHER
+ case PUBKEY_ALGO_RSA:
+ case PUBKEY_ALGO_RSA_E:
+ case PUBKEY_ALGO_RSA_S:
+ rc = do_check( cert );
+ break;
+ #endif
default: rc = G10ERR_PUBKEY_ALGO;
}
if( get_passphrase_fd() != -1 )
break;
}
+
return rc;
}
diff --git a/g10/sign.c b/g10/sign.c
index 104aedb42..598f60998 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -170,17 +170,19 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( opt.armor && !outfile )
iobuf_push_filter( out, armor_filter, &afx );
- write_comment( out, "#created by GNUPG v" VERSION " ("
+ else
+ write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
- if( opt.compress && !outfile )
- iobuf_push_filter( out, compress_filter, &zfx );
-
if( encrypt ) {
efx.pkc_list = pkc_list;
/* fixme: set efx.cfx.datalen if known */
iobuf_push_filter( out, encrypt_filter, &efx );
}
+ if( opt.compress && !outfile )
+ iobuf_push_filter( out, compress_filter, &zfx );
+
+
if( !detached ) {
/* loop over the secret certificates and build headers */
for( skc_rover = skc_list; skc_rover; skc_rover = skc_rover->next ) {
@@ -410,7 +412,6 @@ int
clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
{
armor_filter_context_t afx;
- compress_filter_context_t zfx;
text_filter_context_t tfx;
MD_HANDLE textmd = NULL;
IOBUF inp = NULL, out = NULL;
@@ -420,7 +421,6 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
SKC_LIST skc_rover = NULL;
memset( &afx, 0, sizeof afx);
- memset( &zfx, 0, sizeof zfx);
memset( &tfx, 0, sizeof tfx);
init_packet( &pkt );