diff options
author | Werner Koch <[email protected]> | 2024-09-09 14:41:35 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2024-09-09 14:47:04 +0000 |
commit | d528d0b065334b4c8c52e66441160e308b51d24f (patch) | |
tree | 6d4e920f8b0c9fdda0515d8e035b3533ee475aba /g10/mainproc.c | |
parent | gpg: Improve detection of input data read errors. (diff) | |
download | gnupg-d528d0b065334b4c8c52e66441160e308b51d24f.tar.gz gnupg-d528d0b065334b4c8c52e66441160e308b51d24f.zip |
gpg: New commands --add-recipients and --change-recipients.
* g10/gpg.c (aAddRecipients, aChangeRecipients): New consts.
(opts): Add --add-recipients and --change-recipients.
(main): Handle them.
* g10/gpg.h (struct server_control_s): Add fields modify_recipients,
clear_recipients, and last_read_ctb.
* g10/armor.c (was_armored): New.
* g10/decrypt.c (decrypt_message): Add optional arg 'remusr'. Handle
re-encryption if desired.
* g10/encrypt.c (write_pubkey_enc): Factor info printing out to ...
(show_encrypted_for_user_info): new.
(reencrypt_to_new_recipients): New.
* g10/packet.h (struct parse_packet_ctx_s): Add fields only_fookey_enc
and last_ctb.
(init_parse_packet): Clear them.
* g10/parse-packet.c (parse): Store CTB in the context. Early return
on pubkey_enc and symkey_enc packets if requested.
* g10/mainproc.c (proc_encrypted): Allow for PKT being NULL. Return
early in modify-recipients mode.
(proc_encryption_packets): Add two optional args 'r_dek' and 'r_list'.
Adjust callers. Call do_proc_packets in modify-recipients mode
depending on the optional args.
(do_proc_packets): Add arg 'keep_dek_and_list'. Adjust callers. Save
the last read CTB in CTRL and return after the last fooenc_enc
packets.
--
This basically works but does not yet handle symmetric encrypted
packets (symkey_enc).
GnuPG-bug-id: 1825
(Yes, this is an at least 9 year old feature request)
Diffstat (limited to 'g10/mainproc.c')
-rw-r--r-- | g10/mainproc.c | 95 |
1 files changed, 78 insertions, 17 deletions
diff --git a/g10/mainproc.c b/g10/mainproc.c index 3bb46b574..2429e1006 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -116,7 +116,7 @@ static int literals_seen; /*** Local prototypes. ***/ -static int do_proc_packets (CTX c, iobuf_t a); +static int do_proc_packets (CTX c, iobuf_t a, int keep_dek_and_list); static void list_node (CTX c, kbnode_t node); static void proc_tree (CTX c, kbnode_t node); @@ -580,10 +580,15 @@ proc_encrypted (CTX c, PACKET *pkt) int early_plaintext = literals_seen; unsigned int compliance_de_vs = 0; - if (pkt->pkttype == PKT_ENCRYPTED_AEAD) - c->seen_pkt_encrypted_aead = 1; - if (pkt->pkttype == PKT_ENCRYPTED_MDC) - c->seen_pkt_encrypted_mdc = 1; + if (pkt) + { + if (pkt->pkttype == PKT_ENCRYPTED_AEAD) + c->seen_pkt_encrypted_aead = 1; + if (pkt->pkttype == PKT_ENCRYPTED_MDC) + c->seen_pkt_encrypted_mdc = 1; + } + else /* No PKT indicates the the add-recipients mode. */ + log_assert (c->ctrl->modify_recipients); if (early_plaintext) { @@ -650,6 +655,22 @@ proc_encrypted (CTX c, PACKET *pkt) if (c->dek && opt.verbose > 1) log_info (_("public key encrypted data: good DEK\n")); + if (c->ctrl->modify_recipients) + { + if (c->anchor) + { + log_error ("command not possible with nested data\n"); + write_status_errcode ("decryption.mod_recp", GPG_ERR_BAD_DATA); + xfree (c->dek); + c->dek = NULL; + return; + } + literals_seen++; + /* Simply return here. Our caller will then test for DEK and + * the PK_list to decide whether decryption worked. */ + return; + } + if (!opt.show_only_session_key) write_status (STATUS_BEGIN_DECRYPTION); @@ -1112,7 +1133,7 @@ static int proc_encrypt_cb (iobuf_t a, void *info ) { CTX c = info; - return proc_encryption_packets (c->ctrl, info, a ); + return proc_encryption_packets (c->ctrl, info, a, NULL, NULL); } @@ -1502,7 +1523,7 @@ proc_packets (ctrl_t ctrl, void *anchor, iobuf_t a ) c->ctrl = ctrl; c->anchor = anchor; - rc = do_proc_packets (c, a); + rc = do_proc_packets (c, a, 0); xfree (c); return rc; @@ -1525,7 +1546,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a, c->signed_data.used = !!signedfiles; c->sigfilename = sigfilename; - rc = do_proc_packets (c, a); + rc = do_proc_packets (c, a, 0); /* If we have not encountered any signature we print an error messages, send a NODATA status back and return an error code. @@ -1568,7 +1589,7 @@ proc_signature_packets_by_fd (ctrl_t ctrl, void *anchor, iobuf_t a, c->signed_data.data_names = NULL; c->signed_data.used = (signed_data_fd != GNUPG_INVALID_FD); - rc = do_proc_packets (c, a); + rc = do_proc_packets (c, a, 0); /* If we have not encountered any signature we print an error messages, send a NODATA status back and return an error code. @@ -1592,8 +1613,13 @@ proc_signature_packets_by_fd (ctrl_t ctrl, void *anchor, iobuf_t a, } -int -proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a ) +/* Handle encryption packets. If called recursively the caller's CTX + * should be given for ANCHOR. If R_DEK and R_LIST are not NULL the + * DEK (or NULL) is returned there and the list at R_LIST; the caller + * needs to release them; even if the function returns an error. */ +gpg_error_t +proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a, + DEK **r_dek, struct pubkey_enc_list **r_list) { CTX c = xmalloc_clear (sizeof *c); int rc; @@ -1601,7 +1627,16 @@ proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a ) c->ctrl = ctrl; c->anchor = anchor; c->encrypt_only = 1; - rc = do_proc_packets (c, a); + if (r_dek && r_list) + { + rc = do_proc_packets (c, a, 1); + *r_dek = c->dek; + c->dek = NULL; + *r_list = c->pkenc_list; + c->pkenc_list = NULL; + } + else + rc = do_proc_packets (c, a, 0); xfree (c); return rc; } @@ -1626,8 +1661,11 @@ check_nesting (CTX c) } +/* Main processing loop. If KEEP_DEK_AND_LIST is set the DEK and + * PKENC_LIST of the context C are not released at the end of the + * function. The caller is then required to do this. */ static int -do_proc_packets (CTX c, iobuf_t a) +do_proc_packets (CTX c, iobuf_t a, int keep_dek_and_list) { PACKET *pkt; struct parse_packet_ctx_s parsectx; @@ -1648,6 +1686,18 @@ do_proc_packets (CTX c, iobuf_t a) any_data = 1; if (rc) { + if (c->ctrl->modify_recipients && gpg_err_code (rc) == GPG_ERR_TRUE) + { + /* Save the last read CTB (which was the last byte + * actually read from the input) and get out of the + * loop. */ + c->ctrl->last_read_ctb = parsectx.last_ctb; + /* We need to call the first part of the encrypted data + * handler to get the DEK. */ + proc_encrypted (c, NULL); + rc = -1; + break; + } free_packet (pkt, &parsectx); /* Stop processing when an invalid packet has been encountered * but don't do so when we are doing a --list-packets. */ @@ -1706,8 +1756,19 @@ do_proc_packets (CTX c, iobuf_t a) goto leave; case PKT_SIGNATURE: newpkt = add_signature (c, pkt); break; - case PKT_SYMKEY_ENC: proc_symkey_enc (c, pkt); break; - case PKT_PUBKEY_ENC: proc_pubkey_enc (c, pkt); break; + + case PKT_SYMKEY_ENC: + case PKT_PUBKEY_ENC: + /* In --add-recipients mode set the stop flag as soon as + * we see the first of these packets. */ + if (c->ctrl->modify_recipients) + parsectx.only_fookey_enc = 1; + if (pkt->pkttype == PKT_SYMKEY_ENC) + proc_symkey_enc (c, pkt); + else + proc_pubkey_enc (c, pkt); + break; + case PKT_ENCRYPTED: case PKT_ENCRYPTED_MDC: case PKT_ENCRYPTED_AEAD: proc_encrypted (c, pkt); break; @@ -1783,8 +1844,8 @@ do_proc_packets (CTX c, iobuf_t a) leave: - release_list (c); - xfree(c->dek); + if (!keep_dek_and_list) + release_list (c); free_packet (pkt, &parsectx); deinit_parse_packet (&parsectx); xfree (pkt); |