1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

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)
This commit is contained in:
Werner Koch 2024-09-09 16:41:35 +02:00
parent 2cc340eca0
commit d528d0b065
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
11 changed files with 332 additions and 67 deletions

View file

@ -46,6 +46,30 @@ static int encrypt_simple( const char *filename, int mode, int use_seskey );
static int write_pubkey_enc_from_list (ctrl_t ctrl,
PK_LIST pk_list, DEK *dek, iobuf_t out);
/* Helper for show the "encrypted for USER" during encryption.
* PUBKEY_USAGE is used to figure out whether this is an ADSK key. */
static void
show_encrypted_for_user_info (ctrl_t ctrl, unsigned int pubkey_usage,
PKT_pubkey_enc *enc, DEK *dek)
{
char *ustr = get_user_id_string_native (ctrl, enc->keyid);
if ((pubkey_usage & PUBKEY_USAGE_RENC))
{
char *tmpustr = xstrconcat (ustr, " [ADSK]", NULL);
xfree (ustr);
ustr = tmpustr;
}
log_info (_("%s/%s.%s encrypted for: \"%s\"\n"),
openpgp_pk_algo_name (enc->pubkey_algo),
openpgp_cipher_algo_name (dek->algo),
dek->use_aead? openpgp_aead_algo_name (dek->use_aead)
/**/ : "CFB",
ustr );
xfree (ustr);
}
/****************
* Encrypt FILENAME with only the symmetric cipher. Take input from
* stdin if FILENAME is NULL. If --force-aead is used we use an SKESK.
@ -389,10 +413,11 @@ use_mdc (pk_list_t pk_list,int algo)
}
/* We don't want to use use_seskey yet because older gnupg versions
can't handle it, and there isn't really any point unless we're
making a message that can be decrypted by a public key or
passphrase. */
/* This function handles the --symmetric only (MODE true) and --store
* (MODE false) cases. We don't want to use USE_SESKEY by default
* very old gnupg versions can't handle it, and there isn't really any
* point unless we're making a message that can be decrypted by a
* public key or passphrase. */
static int
encrypt_simple (const char *filename, int mode, int use_seskey)
{
@ -1034,6 +1059,90 @@ encrypt_crypt (ctrl_t ctrl, gnupg_fd_t filefd, const char *filename,
}
/* Re-encrypt files with a set of new recipients. Note that this
* function is called by decrypt_message. INFP is the iobuf from the
* input file which is positioned right after the pubkey_enc and
* symkey_enc packets. */
gpg_error_t
reencrypt_to_new_recipients (ctrl_t ctrl, int armor, const char *filename,
iobuf_t infp, strlist_t recipients,
DEK *dek, struct pubkey_enc_list *pkenc_list)
{
gpg_error_t err;
int save_no_encrypt_to;
pk_list_t newpk_list = NULL;
iobuf_t outfp = NULL;
armor_filter_context_t *outafx = NULL;
PACKET pkt;
struct pubkey_enc_list *el;
unsigned int count;
/* Get the keys for all additional recipients but do not encrypt to
* the encrypt-to keys. */
save_no_encrypt_to = opt.no_encrypt_to;
opt.no_encrypt_to = 1;
err = build_pk_list (ctrl, recipients, &newpk_list);
opt.no_encrypt_to = save_no_encrypt_to;
if (err)
goto leave;
/* Note that we use by default the suffixes .gpg or .asc */
err = open_outfile (GNUPG_INVALID_FD, filename, armor? 1:0, 0, &outfp);
if (err)
goto leave;
if (armor)
{
outafx = new_armor_context ();
push_armor_filter (outafx, outfp);
}
/* Write the new recipients first. */
err = write_pubkey_enc_from_list (ctrl, newpk_list, dek, outfp);
if (err)
goto leave;
/* The write the old recipients in --add-recipients mode. */
for (count=0, el = pkenc_list; el; el = el->next, count++)
if (!ctrl->clear_recipients)
{
if (opt.verbose)
show_encrypted_for_user_info (ctrl, 0, &el->d, dek);
init_packet (&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;
pkt.pkt.pubkey_enc = &el->d;
err = build_packet (outfp, &pkt);
if (err)
log_error ("build_packet(pubkey_enc) failed: %s\n",
gpg_strerror (err));
}
if (ctrl->clear_recipients && opt.verbose)
log_info (_("number of removed recipients: %u\n"), count);
iobuf_put (outfp, ctrl->last_read_ctb);
/* Finally copy the bulk of the message. */
iobuf_copy (outfp, infp);
if ((err = iobuf_error (infp)))
log_error (_("error reading '%s': %s\n"),
iobuf_get_fname_nonnull (infp), gpg_strerror (err));
else if ((err = iobuf_error (outfp)))
log_error (_("error writing '%s': %s\n"),
iobuf_get_fname_nonnull (outfp), gpg_strerror (err));
leave:
if (err)
iobuf_cancel (outfp);
else
iobuf_close (outfp);
release_armor_context (outafx);
release_pk_list (newpk_list);
return err;
}
/*
* Filter to do a complete public key encryption.
*/
@ -1144,22 +1253,7 @@ write_pubkey_enc (ctrl_t ctrl,
else
{
if ( opt.verbose )
{
char *ustr = get_user_id_string_native (ctrl, enc->keyid);
if ((pk->pubkey_usage & PUBKEY_USAGE_RENC))
{
char *tmpustr = xstrconcat (ustr, " [ADSK]", NULL);
xfree (ustr);
ustr = tmpustr;
}
log_info (_("%s/%s.%s encrypted for: \"%s\"\n"),
openpgp_pk_algo_name (enc->pubkey_algo),
openpgp_cipher_algo_name (dek->algo),
dek->use_aead? openpgp_aead_algo_name (dek->use_aead)
/**/ : "CFB",
ustr );
xfree (ustr);
}
show_encrypted_for_user_info (ctrl, pk->pubkey_usage, enc, dek);
/* And write it. */
init_packet (&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;