Encrypt the parameters.

This commit is contained in:
Neal H. Walfield 2016-02-08 00:18:00 +01:00
parent 28fe48cf92
commit fd7dc535f3
9 changed files with 564 additions and 67 deletions

View File

@ -654,3 +654,10 @@ void
tofu_end_batch_update (void)
{
}
gpg_error_t
mailing_list_reprotect (KBNODE kb)
{
(void) kb;
return 0;
}

View File

@ -37,6 +37,7 @@
#include "../kbx/keybox.h"
#include "keydb.h"
#include "i18n.h"
#include "mailing-list.h"
static int active_handles;
@ -1525,6 +1526,10 @@ keydb_update_keyblock (KEYDB_HANDLE hd, kbnode_t kb)
assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
pk = kb->pkt->pkt.public_key;
/* If the mailing list parameters are decrypted, restore the fake
data. */
mailing_list_reprotect (kb);
if (!hd)
return gpg_error (GPG_ERR_INV_ARG);

View File

@ -45,6 +45,7 @@
#include "../common/shareddefs.h"
#include "host2net.h"
#include "mbox-util.h"
#include "mailing-list.h"
/* The default algorithms. If you change them remember to change them
@ -1019,6 +1020,31 @@ write_selfsigs (KBNODE root, PKT_public_key *psk,
session_key_initial.algo = default_cipher_algo ();
make_session_key (&session_key_initial);
/* XXX: Remove. */
// if (DBG_PACKET)
{
char *fn =
xasprintf ("%s/mailing-list-%s-subscriber-list-session-key-initial.txt",
opt.homedir, keystr (psk->keyid));
FILE *fp = fopen (fn, "w");
if (fp)
{
char numbuf[25];
char hexbuf[2 * session_key_initial.keylen + 1];
log_debug ("Writing unencrypted initial session key to %s\n",
fn);
snprintf (numbuf, sizeof numbuf, "%d:", session_key_initial.algo);
bin2hex (session_key_initial.key, session_key_initial.keylen,
hexbuf);
fwrite (numbuf, strlen (numbuf), 1, fp);
fwrite (hexbuf, strlen (hexbuf), 1, fp);
fclose (fp);
}
xfree (fn);
}
/* We don't need ctrl: we are certain that pk_list doesn't
contain a mailing list key, which is the only thing that
write_pubkey_enc_from_list needs ctrl for. */
@ -1042,11 +1068,21 @@ write_selfsigs (KBNODE root, PKT_public_key *psk,
return gpg_error (GPG_ERR_INTERNAL);
}
{
FILE *fp = fopen ("/tmp/subscriber-list-session-key", "w");
fwrite (buffer, len, 1, fp);
fclose (fp);
}
if (MAILING_LIST_DUMP_NOTATIONS)
{
char *fn =
xasprintf ("%s/mailing-list-%s-subscriber-list-session-key-initial.gpg",
opt.homedir, keystr (psk->keyid));
FILE *fp = fopen (fn, "w");
if (fp)
{
log_debug ("Writing encrypted initial session key to %s\n",
fn);
fwrite (buffer, len, 1, fp);
fclose (fp);
}
xfree (fn);
}
notation_blob->next = notations;
notations = notation_blob;

View File

@ -312,6 +312,9 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
keyblock. */
PKT_public_key *ml_ek = NULL;
DEK *deks = NULL;
int ndeks;
/* The first session key. */
DEK session_key_initial;
/* The current session key. */
@ -414,7 +417,7 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
}
/* Make sure we haven't already added this encryption key. Or, if
we have and it is unsubscriber, resubscribe it. */
we have and it is unsubscribed, resubscribe it. */
{
KBNODE n;
char sub_ek_fp[MAX_FINGERPRINT_LEN];
@ -426,11 +429,31 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
{
char fp[MAX_FINGERPRINT_LEN];
size_t fplen;
PKT_public_key *x;
if (n->pkt->pkttype != PKT_PUBLIC_SUBKEY)
continue;
fingerprint_from_pk (n->pkt->pkt.public_key, fp, &fplen);
x = n->pkt->pkt.public_key;
if (gcry_mpi_cmp (x->pkey[0], GCRYMPI_CONST_TWO) == 0)
/* The subkey is still encrypted. Decrypt them all. */
{
err = mailing_list_subscribers_ext (ctrl, ml_kb, NULL,
&deks, &ndeks);
if (err)
{
log_error ("failed to decrypt subscribers' keys: %s",
gpg_strerror (err));
goto out;
}
assert (x->flags.pkey_decrypted);
assert (gcry_mpi_cmp (x->pkey[0], GCRYMPI_CONST_TWO) != 0);
assert (x->timestamp_saved);
}
fingerprint_from_pk (x, fp, &fplen);
if (sub_ek_fplen == fplen && memcmp (sub_ek_fp, fp, fplen) == 0)
/* Got a match! */
break;
@ -439,7 +462,7 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
if (n)
{
/* XXX: If SUB was a subscriber, but is currently
unsubscriber, readd. */
unsubscriber, re-add. */
log_error ("%s is already a subscriber.\n", sub);
goto out;
}
@ -450,10 +473,11 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
access to it) and the current session key (we need to encrypt the
new subscriber's parameters with it). */
{
DEK *deks = NULL;
int ndeks;
err = mailing_list_get_subscriber_list_session_keys (ctrl, ml_kb,
&deks, &ndeks);
/* We may have already gotten the session keys above. If so,
don't repeat the work. */
if (! deks)
err = mailing_list_get_subscriber_list_session_keys (ctrl, ml_kb,
&deks, &ndeks);
if (err)
{
log_error ("Failed to get session keys for mailing list: %s\n",
@ -468,6 +492,7 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
session_key = deks[session_key_i];
xfree (deks);
deks = NULL;
}
/* Make a new subkey using the new subscriber's selected encryption
@ -494,6 +519,31 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
ml_ek->main_keyid[0] = ml_pk->keyid[0];
ml_ek->main_keyid[1] = ml_pk->keyid[1];
ml_ek->pubkey_usage = PUBKEY_USAGE_ENC;
ml_ek->timestamp = make_timestamp();
/* Since the parameters are not unique, make sure the time stamps
are. */
{
KBNODE n;
if (DBG_PACKET)
log_debug ("Choose timestamp: %x, checking that it is unique.\n",
ml_ek->timestamp);
for (n = ml_kb; n; n = n->next)
if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
PKT_public_key *x = n->pkt->pkt.public_key;
if (x->timestamp_saved == ml_ek->timestamp)
{
if (DBG_PACKET)
log_debug ("Timestamp collision! Advancing to %x and restarting\n",
ml_ek->timestamp);
ml_ek->timestamp ++;
/* Restart. (This skips the first node, but that's
never a subkey.) */
n = ml_kb;
continue;
}
}
}
ml_ek->expiredate = 0;
ml_ek->max_expiredate = 0;
ml_ek->prefs = NULL;
@ -508,19 +558,132 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
/* Encrypt the parameters and the current time using the current
session key. */
{
/* Create the data that we want to encrypt. */
iobuf_t params = iobuf_temp ();
int i;
int n = pubkey_get_npkey (ml_ek->pubkey_algo);
/* XXX. */
iobuf_write (params, "XXXYYY ", 7);
for (i = 0; i < n; i ++)
{
/* XXX: Finish me: actually encrypt the keys; don't just copy
them. */
(void) session_key;
ml_ek->pkey[i] = gcry_mpi_copy (ml_ek->pkey[i]);
err = gpg_mpi_write (params, ml_ek->pkey[i]);
ml_ek->pkey[i] = GCRYMPI_CONST_TWO;
if (err)
{
log_error ("encrypting subscriber's key: %s\n",
gpg_strerror (err));
iobuf_close (params);
goto out;
}
}
/* XXX: Encrypt the creation time. */
iobuf_flush_temp (params);
if (MAILING_LIST_DUMP_NOTATIONS)
/* Save the raw data for debugging purposes. */
{
char *ml_pk_keyid = xstrdup (keystr (ml_pk->keyid));
char *fn = xasprintf ("%s/mailing-list-%s-public-key-%s.txt",
opt.homedir, ml_pk_keyid,
keystr (sub_ek->keyid));
FILE *fp = fopen (fn, "w");
xfree (ml_pk_keyid);
if (fp)
{
log_debug ("Writing unencrypted public-key parameters to %s\n", fn);
fwrite (iobuf_get_temp_buffer (params),
iobuf_get_temp_length (params), 1, fp);
fclose (fp);
}
xfree (fn);
}
/* Setup the encryption pipeline. (Based on encrypt_simple.) */
{
PKT_plaintext pt;
PACKET pkt;
cipher_filter_context_t cfx;
int len = iobuf_get_temp_length (params);
iobuf_t in;
in = iobuf_temp_with_content (iobuf_get_temp_buffer (params), len);
iobuf_close (params);
params = NULL;
if (! in)
{
log_error ("failed to create iobuf");
goto out;
}
params = iobuf_temp ();
memset (&pt, 0, sizeof (pt));
pt.namelen = 0;
pt.mode = 'b';
pt.len = len;
pt.new_ctb = 0;
pt.timestamp = sub_ek->timestamp;
pt.buf = in;
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = &pt;
memset (&cfx, 0, sizeof cfx);
cfx.dek = &session_key;
cfx.datalen = calc_packet_length (&pkt);
iobuf_push_filter (params, cipher_filter, &cfx);
err = build_packet (params, &pkt);
if (err)
{
log_error ("building packet: %s\n", gpg_strerror (err));
goto out;
}
}
iobuf_flush_temp (params);
{
char *notation = "public-key@gnupg.org";
char *buffer = iobuf_get_temp_buffer (params);
size_t len = iobuf_get_temp_length (params);
struct notation *notation_blob
= blob_to_notation (notation, buffer, len);
if (! notation_blob)
{
log_bug ("Failed to create notation: %s=<SE-ESK packet, %zd bytes>\n",
notation, len);
err = gpg_error (GPG_ERR_INTERNAL);
goto out;
}
notation_blob->next = notations;
notations = notation_blob;
if (MAILING_LIST_DUMP_NOTATIONS)
{
char *ml_pk_keyid = xstrdup (keystr (ml_pk->keyid));
char *fn = xasprintf ("%s/mailing-list-%s-public-key-%s.gpg",
opt.homedir, ml_pk_keyid,
keystr (sub_ek->keyid));
FILE *fp = fopen (fn, "w");
xfree (ml_pk_keyid);
if (fp)
{
log_debug ("Writing encrypted public-key parameters to %s (because this SED packet is not preceeded by an ESK packet, an OpenPGP implementation assumes that it is IDEA encoded. As such, to manually dump this packet, you need to use --override-session-key).\n", fn);
fwrite (buffer, len, 1, fp);
fclose (fp);
}
xfree (fn);
}
iobuf_close (params);
}
/* Recompute ml_ek->keyid. */
{
@ -598,12 +761,14 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
buffer = iobuf_get_temp_buffer (pk_esk);
len = iobuf_get_temp_length (pk_esk);
/* XXX */
if (DBG_PACKET)
if (MAILING_LIST_DUMP_NOTATIONS)
{
char *fn = xasprintf ("/tmp/subscriber-list-key-%s",
char *ml_pk_keyid = xstrdup (keystr (ml_pk->keyid));
char *fn = xasprintf ("%s/mailing-list-%s-subscriber-list-key-%s.gpg",
opt.homedir, ml_pk_keyid,
keystr (sub_ek->keyid));
FILE *fp = fopen (fn, "w");
xfree (ml_pk_keyid);
if (fp)
{
log_debug ("Writing subscriber-list-key to %s\n", fn);
@ -630,7 +795,7 @@ mailing_list_add_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub)
/* Write the binding signature. */
err = write_keybinding (ml_kb, ml_pk, NULL, ml_ek->pubkey_usage,
make_timestamp(), NULL, notations);
ml_ek->timestamp, NULL, notations);
if (err)
{
log_error ("Error creating key binding: %s\n", gpg_strerror (err));
@ -719,8 +884,9 @@ mailing_list_rm_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub_orig)
goto out;
}
err = mailing_list_get_subscriber_list_session_keys (ctrl, ml_kb,
&deks, &ndeks);
/* Get the session keys and make sure the public keys are
decrypted. */
err = mailing_list_subscribers_ext (ctrl, ml_kb, NULL, &deks, &ndeks);
if (err)
{
log_error ("Failed to get session keys: %s\n", gpg_strerror (err));
@ -845,13 +1011,16 @@ mailing_list_rm_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub_orig)
return gpg_error (GPG_ERR_INTERNAL);
}
{
char *fn = xasprintf ("/tmp/subscriber-list-session-key-%d", ndeks);
FILE *fp = fopen (fn, "w");
xfree (fn);
fwrite (buffer, len, 1, fp);
fclose (fp);
}
if (MAILING_LIST_DUMP_NOTATIONS)
{
char *fn =
xasprintf ("%s/mailing-list-%s-subscriber-list-session-key-%d.gpg",
opt.homedir, keystr (ml_pk->keyid), ndeks);
FILE *fp = fopen (fn, "w");
xfree (fn);
fwrite (buffer, len, 1, fp);
fclose (fp);
}
notation_blob->next = notations;
notations = notation_blob;
@ -907,6 +1076,8 @@ mailing_list_rm_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub_orig)
ek->expiredate = make_timestamp();
mailing_list_reprotect_one (ek);
err = update_keysig_packet (&newsig, sig, ml_pk, NULL, ek,
ml_pk, notations,
keygen_add_key_expire, ek);
@ -953,8 +1124,25 @@ mailing_list_rm_subscriber (ctrl_t ctrl, KBNODE ml_kb, const char *sub_orig)
return err;
}
/* Return the actual subscribers to the mailing list in *PKLISTP and,
in the process, update their public key parameters and creation
time stamp with the actual values taken from the encrypted data.
It is ok for PKLISTP to be NULL. In this case, only KB is
updated.
Calling this function multiple times is okay. It just costs some
extra processing time. */
gpg_error_t
mailing_list_subscribers (ctrl_t ctrl, KBNODE kb, PK_LIST *pklistp)
{
return mailing_list_subscribers_ext (ctrl, kb, pklistp, NULL, NULL);
}
gpg_error_t
mailing_list_subscribers_ext (ctrl_t ctrl, KBNODE kb, PK_LIST *pklistp,
DEK **deksp, int *ndeksp)
{
gpg_error_t err;
@ -967,17 +1155,20 @@ mailing_list_subscribers (ctrl_t ctrl, KBNODE kb, PK_LIST *pklistp)
err = mailing_list_get_subscriber_list_session_keys (ctrl, kb,
&deks, &ndeks);
if (err)
return err;
for (n = kb; n; n = n->next)
{
if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = n->pkt->pkt.public_key;
if (pk->has_expired)
/* The subscriber was removed. */
if (gcry_mpi_cmp (pk->pkey[0], GCRYMPI_CONST_TWO) != 0)
/* Key is already decrypted. No need to do it again. */
{
if (DBG_PACKET)
log_debug ("%s: Skipping subscriber %s who was unsubscribed.\n",
log_debug ("%s: Already decrypted %s.\n",
__func__, keystr (pk->keyid));
pk = NULL;
}
@ -987,34 +1178,131 @@ mailing_list_subscribers (ctrl_t ctrl, KBNODE kb, PK_LIST *pklistp)
PKT_signature *sig = n->pkt->pkt.signature;
struct notation *notations;
struct notation *x;
int session_key = -1;
char *pkenc = NULL;
int pklen = 0;
notations = sig_to_notation (sig);
if (! notations)
continue;
for (x = notations; x; x = x->next)
/* If the public key is encrypted, then this is a subscriber. */
if (strcmp (x->name, "public-key-encrypted-with@gnupg.org") == 0)
/* If the public key is encrypted, then this is a subscriber. */
session_key = atoi (x->value);
else if (strcmp (x->name, "public-key@gnupg.org") == 0)
{
PK_LIST r = xmalloc_clear (sizeof *r);
int i = atoi (x->value);
if (i >= ndeks)
{
log_error ("Unable to decrypt subkey %s: session key %d not available.\n",
keystr (pk->keyid), i);
goto out;
}
/* XXX: Decrypt the public key parameters using the
session key. */
(void) i;
r->pk = copy_public_key (NULL, pk);
r->next = pklist;
pklist = r;
pklen = x->blen;
pkenc = xmalloc (pklen);
memcpy (pkenc, x->bdat, pklen);
}
if (session_key == -1 && pkenc)
log_error ("subkey public-key-encrypted-with@gnupg.org notation, but no public-key@gnupg.org notation!");
else if (session_key != -1 && ! pkenc)
log_error ("subkey public-key@gnupg.org notation, but no public-key-encrypted-with@gnupg.org notation!");
else if (session_key != -1 && pkenc)
{
if (session_key >= ndeks)
log_error ("Unable to decrypt subkey %s: session key %d not available.\n",
keystr (pk->keyid), session_key);
else
{
DEK dek = deks[session_key];
iobuf_t encrypted_data
= iobuf_temp_with_content (pkenc, pklen);
estream_t decrypted_data_fp;
char *decrypted_data = NULL;
size_t len = 0;
/* We don't use an MDC as it adds unnecessary
overhead: notations are stored in the hashed
area, which is signed so an MDC doesn't offer any
extra protection. */
int no_mdc_warn = opt.no_mdc_warn;
int ignore_mdc_error = opt.ignore_mdc_error;
u32 timestamp;
decrypted_data_fp = es_fopenmem (0, "rw,samethread");
if (! decrypted_data_fp)
log_fatal ("Error creating memory stream\n");
opt.no_mdc_warn = 1;
opt.ignore_mdc_error = 1;
err = proc_encrypted_data (ctrl, encrypted_data, &dek,
decrypted_data_fp, &timestamp);
opt.no_mdc_warn = no_mdc_warn;
opt.ignore_mdc_error = ignore_mdc_error;
if (es_fclose_snatch (decrypted_data_fp,
(void **) &decrypted_data, &len))
log_fatal ("error snatching memory stream\n");
pk->flags.pkey_decrypted = 1;
pk->timestamp_saved = pk->timestamp;
pk->timestamp = timestamp;
{
char *p = decrypted_data;
int i;
size_t r;
/* XXX: Remove this check (and the data that we
insert). */
if (memcmp (p, "XXXYYY ", 7) != 0)
log_bug ("Bad data.\n");
p += 7; len -= 7;
for (i = 0; i < pubkey_get_npkey (pk->pubkey_algo); i ++)
{
if (len == 0)
err = GPG_ERR_TOO_SHORT;
if (! err)
err = gcry_mpi_scan (&pk->pkey[i], GCRYMPI_FMT_PGP,
p, len, &r);
if (err)
{
log_error ("Error parsing MPI %d\n", i + 1);
goto out;
}
p += r;
len -= r;
}
}
/* Recompute ml_ek->keyid. */
{
char fp[MAX_FINGERPRINT_LEN];
size_t fplen;
u32 keyid[2];
char *keyid_old
= format_keyid (pk->keyid, KF_DEFAULT, NULL, 0);
fingerprint_from_pk (pk, fp, &fplen);
keyid_from_fingerprint (fp, fplen, keyid);
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
if (DBG_PACKET)
log_debug ("Decrypted %s -> %s\n",
keyid_old, keystr (keyid));
}
xfree (decrypted_data);
if (pklistp && ! pk->has_expired)
{
PK_LIST r;
r = xmalloc_clear (sizeof *r);
r->pk = copy_public_key (NULL, pk);
r->next = pklist;
pklist = r;
}
}
}
xfree (pkenc);
free_notation (notations);
}
else
@ -1029,12 +1317,64 @@ mailing_list_subscribers (ctrl_t ctrl, KBNODE kb, PK_LIST *pklistp)
}
out:
xfree (deks);
if (! err && deksp)
{
*deksp = deks;
*ndeksp = ndeks;
}
else
xfree (deks);
if (err)
release_pk_list (pklist);
else
else if (pklistp)
*pklistp = pklist;
return err;
}
/* mailing_list_subscribers (and related functions) decrypt the
mailing list parameters and update the keyblock. These should
never be written to disk. This function restores the fake
values. */
gpg_error_t
mailing_list_reprotect_one (PKT_public_key *pk)
{
if (pk->flags.pkey_decrypted)
{
int i;
for (i = 0; i < pubkey_get_npkey (pk->pubkey_algo); i ++)
pk->pkey[i] = GCRYMPI_CONST_TWO;
pk->timestamp = pk->timestamp_saved;
pk->timestamp_saved = 0;
pk->flags.pkey_decrypted = 0;
}
return 0;
}
gpg_error_t
mailing_list_reprotect (KBNODE kb)
{
gpg_error_t err = 0;
PKT_public_key *pk = kb->pkt->pkt.public_key;
KBNODE n;
if (! pk->flags.mailing_list)
/* Not a mailing list key. Nothing to do. */
return 0;
for (n = kb; n; n = n->next)
{
if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = n->pkt->pkt.public_key;
err = mailing_list_reprotect_one (pk);
if (err)
return err;
}
}
return err;
}

View File

@ -24,6 +24,9 @@
#include "util.h"
#include "dek.h"
/*#define MAILING_LIST_DUMP_NOTATIONS 1*/
#define MAILING_LIST_DUMP_NOTATIONS 0
void kbnode_dump (KBNODE kb);
/* Get a copy of all the session keys and store them in *DEKS and the
@ -41,4 +44,12 @@ gpg_error_t mailing_list_rm_subscriber (ctrl_t ctrl, KBNODE ml_kb,
gpg_error_t mailing_list_subscribers (ctrl_t ctrl, KBNODE kb,
PK_LIST *pklistp);
gpg_error_t mailing_list_subscribers_ext (ctrl_t ctrl, KBNODE kb,
PK_LIST *pklistp,
DEK **deksp, int *ndeksp);
gpg_error_t mailing_list_reprotect_one (PKT_public_key *pk);
gpg_error_t mailing_list_reprotect (KBNODE kb);
#endif

View File

@ -71,6 +71,7 @@ struct mainproc_context
int encrypt_only; /* Process only encryption messages. */
int symkey_only; /* Just process a SK-ESK packet. */
int pubkey_only; /* Just process a PK-ESK packet. */
int encrypted_data_only; /* Just process encrypted data packets. */
/* Name of the file with the complete signature or the file with the
detached signature. This is currently only used to deduce the
@ -98,6 +99,8 @@ struct mainproc_context
int trustletter; /* Temporary usage in list_node. */
ulong symkeys;
struct kidlist_item *pkenc_list; /* List of encryption packets. */
estream_t outputfp; /* Overrides where to send the contents of the message. */
u32 timestamp; /* Timestamp stored in the last literal packet. */
struct {
unsigned int sig_seen:1; /* Set to true if a signature packet
has been seen. */
@ -142,7 +145,7 @@ release_list( CTX c )
c->any.data = 0;
c->any.uncompress_failed = 0;
c->last_was_session_key = 0;
if (! (c->symkey_only || c->pubkey_only))
if (! (c->symkey_only || c->pubkey_only || c->encrypted_data_only))
{
xfree (c->dek);
c->dek = NULL;
@ -663,8 +666,11 @@ proc_encrypted (CTX c, PACKET *pkt)
* ways to specify the session key (symmmetric and PK). */
}
xfree (c->dek);
c->dek = NULL;
if (! c->encrypted_data_only)
{
xfree (c->dek);
c->dek = NULL;
}
free_packet (pkt);
c->last_was_session_key = 0;
write_status (STATUS_END_DECRYPTION);
@ -765,12 +771,25 @@ proc_plaintext( CTX c, PACKET *pkt )
if (!rc)
{
rc = handle_plaintext (pt, &c->mfx, c->sigs_only, clearsig);
estream_t outputfp = NULL;
CTX ci;
for (ci = c; ci && ! outputfp; ci = ci->anchor)
outputfp = ci->outputfp;
rc = handle_plaintext (pt, &c->mfx, c->sigs_only, outputfp, clearsig);
if (gpg_err_code (rc) == GPG_ERR_EACCES && !c->sigs_only)
{
/* Can't write output but we hash it anyway to check the
signature. */
rc = handle_plaintext( pt, &c->mfx, 1, clearsig );
rc = handle_plaintext( pt, &c->mfx, 1, NULL, clearsig);
}
if (! rc)
{
/* Save the time stamp in the root. */
for (ci = c; ci->anchor; ci = ci->anchor)
;
ci->timestamp = pt->timestamp;
}
}
@ -1291,6 +1310,30 @@ proc_pubkey_packet (ctrl_t ctrl, iobuf_t a, DEK *dek)
return rc;
}
int
proc_encrypted_data (ctrl_t ctrl, iobuf_t input, DEK *dek,
estream_t outputfp, u32 *timestamp)
{
CTX c = xmalloc_clear (sizeof *c);
int rc;
c->ctrl = ctrl;
c->encrypted_data_only = 1;
c->dek = dek;
c->outputfp = outputfp;
reset_literals_seen();
rc = do_proc_packets (ctrl, c, input);
reset_literals_seen();
if (timestamp)
*timestamp = c->timestamp;
xfree (c);
return rc;
}
int
proc_signature_packets_by_fd (ctrl_t ctrl,
void *anchor, iobuf_t a, int signed_data_fd )
@ -1416,9 +1459,10 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_USER_ID:
case PKT_SIGNATURE:
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
case PKT_SIGNATURE:
case PKT_PLAINTEXT:
case PKT_COMPRESSED:
case PKT_ONEPASS_SIG:
@ -1438,9 +1482,10 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_USER_ID:
case PKT_SIGNATURE:
case PKT_SYMKEY_ENC:
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
case PKT_SIGNATURE:
case PKT_PLAINTEXT:
case PKT_COMPRESSED:
case PKT_ONEPASS_SIG:
@ -1453,6 +1498,30 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
default: newpkt = 0; break;
}
}
else if (c->encrypted_data_only)
{
switch (pkt->pkttype)
{
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_USER_ID:
case PKT_SYMKEY_ENC:
case PKT_PUBKEY_ENC:
case PKT_SIGNATURE:
case PKT_PLAINTEXT:
case PKT_COMPRESSED:
case PKT_ONEPASS_SIG:
case PKT_GPG_CONTROL:
write_status_text (STATUS_UNEXPECTED, "0");
rc = GPG_ERR_UNEXPECTED;
goto leave;
case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC:
proc_encrypted (c, pkt); break;
default: newpkt = 0; break;
}
}
else if (c->sigs_only)
{
switch (pkt->pkttype)
@ -1563,8 +1632,25 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
leave:
if (opt.show_session_key && c->dek)
{
char numbuf[25];
char *hexbuf;
snprintf (numbuf, sizeof numbuf, "%d:", c->dek->algo);
hexbuf = bin2hex (c->dek->key, c->dek->keylen, NULL);
if (!hexbuf)
{
rc = gpg_error_from_syserror ();
goto leave;
}
log_info ("session key: '%s%s'\n", numbuf, hexbuf);
write_status_strings (STATUS_SESSION_KEY, numbuf, hexbuf, NULL);
xfree (hexbuf);
}
release_list (c);
if (! (c->symkey_only || c->pubkey_only))
if (! (c->symkey_only || c->pubkey_only || c->encrypted_data_only))
xfree(c->dek);
free_packet (pkt);
xfree (pkt);

View File

@ -269,6 +269,7 @@ struct seckey_info
typedef struct
{
u32 timestamp; /* key made */
u32 timestamp_saved; /* The fake timestamp (for when the key was encrypted) */
u32 expiredate; /* expires at this date or 0 if not at all */
u32 max_expiredate; /* must not expire past this date */
struct revoke_info revoked;
@ -300,6 +301,7 @@ typedef struct
unsigned int serialno_valid:1;/* SERIALNO below is valid. */
unsigned int exact:1; /* Found via exact (!) search. */
unsigned int mailing_list:1;
unsigned int pkey_decrypted:1;/* Never ever save this keyblock to disk. */
} flags;
PKT_user_id *user_id; /* If != NULL: found by that uid. */
struct revocation_key *revkey;
@ -420,6 +422,8 @@ int proc_signature_packets (ctrl_t ctrl, void *ctx, iobuf_t a,
strlist_t signedfiles, const char *sigfile );
int proc_symkey_packet (ctrl_t ctrl, iobuf_t a, DEK *dek);
int proc_pubkey_packet (ctrl_t ctrl, iobuf_t a, DEK *dek);
int proc_encrypted_data (ctrl_t ctrl, iobuf_t a, DEK *dek, estream_t outputfp,
u32 *timestamp);
int proc_signature_packets_by_fd (ctrl_t ctrl,
void *anchor, IOBUF a, int signed_data_fd );
@ -673,7 +677,7 @@ int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek );
gpg_error_t get_output_file (const byte *embedded_name, int embedded_namelen,
iobuf_t data, char **fnamep, estream_t *fpp);
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int nooutput, int clearsig );
int nooutput, estream_t outputfp, int clearsig);
int ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2,
const char *inname, int textmode );

View File

@ -211,10 +211,10 @@ get_output_file (const byte *embedded_name, int embedded_namelen,
* from the plaintext. */
int
handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
int nooutput, int clearsig)
int nooutput, estream_t fp, int clearsig)
{
int user_supplied_fp = !! fp;
char *fname = NULL;
estream_t fp = NULL;
static off_t count = 0;
int err = 0;
int c;
@ -248,7 +248,7 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
}
}
if (! nooutput)
if (! nooutput && !fp)
{
err = get_output_file (pt->name, pt->namelen, pt->buf, &fname, &fp);
if (err)
@ -491,7 +491,8 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
pt->buf = NULL;
}
if (fp && fp != es_stdout && fp != opt.outfp && es_fclose (fp))
if (fp && fp != es_stdout && fp != opt.outfp && ! user_supplied_fp
&& es_fclose (fp))
{
err = gpg_error_from_syserror ();
log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));

View File

@ -466,3 +466,10 @@ void
tofu_end_batch_update (void)
{
}
gpg_error_t
mailing_list_reprotect (KBNODE kb)
{
(void) kb;
return 0;
}