1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-03 12:11:33 +01:00

gpg: Add support for unwrapping the outer level of encryption.

* g10/decrypt-data.c (decrypt_data): If OPT.UNWRAP_ENCRYPTION is set,
copy the data to the output file instead of continuing to process it.
* g10/gpg.c (enum cmd_and_opt_values): Add new value oUnwrap.
(opts): Handle oUnwrap.
(main): Likewise.
* g10/options.h (opt): Add field unwrap_encryption.
* g10/plaintext.c (handle_plaintext): Break the output file selection
functionality into ...
(get_output_file): ... this new function.

--
Signed-off-by: Neal H. Walfield <neal@g10code.com>
GnuPG-bug-id: 1060
Debian-bug-id: 282061
This commit is contained in:
Neal H. Walfield 2015-11-05 12:20:42 +01:00
parent fd4b9e2328
commit ec409e62ae
5 changed files with 130 additions and 48 deletions

View File

@ -221,7 +221,38 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
else
iobuf_push_filter ( ed->buf, decode_filter, dfx );
if (opt.unwrap_encryption)
{
char *filename;
estream_t fp;
rc = get_output_file ("", 0, ed->buf, &filename, &fp);
if (! rc)
{
iobuf_t output = iobuf_esopen (fp, "w", 0);
armor_filter_context_t *afx = NULL;
if (opt.armor)
{
afx = new_armor_context ();
push_armor_filter (afx, output);
}
iobuf_copy (output, ed->buf);
if ((rc = iobuf_error (ed->buf)))
log_error (_("error reading: %s\n"),
filename, gpg_strerror (rc));
else if ((rc = iobuf_error (output)))
log_error (_("error writing output ('%s'): %s\n"),
filename, gpg_strerror (rc));
iobuf_close (output);
if (afx)
release_armor_context (afx);
}
}
else
proc_packets (ctrl, procctx, ed->buf );
ed->buf = NULL;
if (dfx->eof_seen > 1 )
rc = gpg_error (GPG_ERR_INV_PACKET);

View File

@ -391,6 +391,7 @@ enum cmd_and_opt_values
oTOFUDefaultPolicy,
oTOFUDBFormat,
oWeakDigest,
oUnwrap,
oNoop
};
@ -753,6 +754,7 @@ static ARGPARSE_OPTS opts[] = {
"personal-compress-preferences", "@"),
ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
ARGPARSE_s_s (oWeakDigest, "weak-digest","@"),
ARGPARSE_s_n (oUnwrap, "unwrap", "@"),
/* Aliases. I constantly mistype these, and assume other people do
as well. */
@ -3147,6 +3149,9 @@ main (int argc, char **argv)
case oWeakDigest:
additional_weak_digest(pargs.r.ret_str);
break;
case oUnwrap:
opt.unwrap_encryption = 1;
break;
case oDisplay:
set_opt_session_env ("DISPLAY", pargs.r.ret_str);

View File

@ -262,6 +262,8 @@ struct
int passphrase_repeat;
int pinentry_mode;
int unwrap_encryption;
} opt;
/* CTRL is used to keep some global variables we currently can't

View File

@ -663,6 +663,8 @@ int handle_compressed (ctrl_t ctrl, void *ctx, PKT_compressed *cd,
int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/
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 ask_for_detached_datafile( gcry_md_hd_t md, gcry_md_hd_t md2,

View File

@ -40,53 +40,29 @@
#include "i18n.h"
/* Handle a plaintext packet. If MFX is not NULL, update the MDs
* Note: We should have used the filter stuff here, but we have to add
* some easy mimic to set a read limit, so we calculate only the bytes
* from the plaintext. */
int
handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
int nooutput, int clearsig)
/* Get the output filename. On success, the actual filename that is
used is set in *FNAMEP and a filepointer is returned in *FP.
EMBEDDED_NAME AND EMBEDDED_NAMELEN are normally stored in a
plaintext packet. EMBEDDED_NAMELEN should not include any NUL
terminator (EMBEDDED_NAME does not need to be NUL terminated).
DATA is the iobuf containing the input data. We just use it to get
the input file's filename.
On success, the caller is responsible for calling xfree on *FNAMEP
and calling es_close on *FPP. */
gpg_error_t
get_output_file (const byte *embedded_name, int embedded_namelen,
iobuf_t data, char **fnamep, estream_t *fpp)
{
gpg_error_t err = 0;
char *fname = NULL;
estream_t fp = NULL;
static off_t count = 0;
int err = 0;
int c;
int convert = (pt->mode == 't' || pt->mode == 'u');
#ifdef __riscos__
int filetype = 0xfff;
#endif
/* Let people know what the plaintext info is. This allows the
receiving program to try and do something different based on the
format code (say, recode UTF-8 to local). */
if (!nooutput && is_status_enabled ())
{
char status[50];
/* Better make sure that stdout has been flushed in case the
output will be written to it. This is to make sure that no
not-yet-flushed stuff will be written after the plaintext
status message. */
es_fflush (es_stdout);
snprintf (status, sizeof status,
"%X %lu ", (byte) pt->mode, (ulong) pt->timestamp);
write_status_text_and_buffer (STATUS_PLAINTEXT,
status, pt->name, pt->namelen, 0);
if (!pt->is_partial)
{
snprintf (status, sizeof status, "%lu", (ulong) pt->len);
write_status_text (STATUS_PLAINTEXT_LENGTH, status);
}
}
int nooutput = 0;
/* Create the filename as C string. */
if (nooutput)
;
else if (opt.outfp)
if (opt.outfp)
{
fname = xtrystrdup ("[FP]");
if (!fname)
@ -104,16 +80,17 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
goto leave;
}
}
else if (pt->namelen == 8 && !memcmp (pt->name, "_CONSOLE", 8))
else if (embedded_namelen == 8 && !memcmp (embedded_name, "_CONSOLE", 8))
{
log_info (_("data not saved; use option \"--output\" to save it\n"));
nooutput = 1;
}
else if (!opt.flags.use_embedded_filename)
{
fname = make_outfile_name (iobuf_get_real_fname (pt->buf));
if (data)
fname = make_outfile_name (iobuf_get_real_fname (data));
if (!fname)
fname = ask_outfile_name (pt->name, pt->namelen);
fname = ask_outfile_name (embedded_name, embedded_namelen);
if (!fname)
{
err = gpg_error (GPG_ERR_GENERAL); /* Can't create file. */
@ -121,7 +98,7 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
}
}
else
fname = utf8_to_native (pt->name, pt->namelen, 0);
fname = utf8_to_native (embedded_name, embedded_namelen, 0);
if (nooutput)
;
@ -205,7 +182,8 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
/* If there's a ,xxx extension in the embedded filename,
use that, else check whether the user input (in fname)
has a ,xxx appended, then use that in preference */
if ((c = riscos_get_filetype_from_string (pt->name, pt->namelen)) != -1)
if ((c = riscos_get_filetype_from_string (embedded_name,
embedded_namelen)) != -1)
filetype = c;
if ((c = riscos_get_filetype_from_string (fname, strlen (fname))) != -1)
filetype = c;
@ -213,6 +191,70 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
}
#endif /* __riscos__ */
leave:
if (err)
{
if (fp && fp != es_stdout && fp != opt.outfp)
es_fclose (fp);
xfree (fname);
return err;
}
*fnamep = fname;
*fpp = fp;
return 0;
}
/* Handle a plaintext packet. If MFX is not NULL, update the MDs
* Note: We should have used the filter stuff here, but we have to add
* some easy mimic to set a read limit, so we calculate only the bytes
* from the plaintext. */
int
handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx,
int nooutput, int clearsig)
{
char *fname = NULL;
estream_t fp = NULL;
static off_t count = 0;
int err = 0;
int c;
int convert = (pt->mode == 't' || pt->mode == 'u');
#ifdef __riscos__
int filetype = 0xfff;
#endif
/* Let people know what the plaintext info is. This allows the
receiving program to try and do something different based on the
format code (say, recode UTF-8 to local). */
if (!nooutput && is_status_enabled ())
{
char status[50];
/* Better make sure that stdout has been flushed in case the
output will be written to it. This is to make sure that no
not-yet-flushed stuff will be written after the plaintext
status message. */
es_fflush (es_stdout);
snprintf (status, sizeof status,
"%X %lu ", (byte) pt->mode, (ulong) pt->timestamp);
write_status_text_and_buffer (STATUS_PLAINTEXT,
status, pt->name, pt->namelen, 0);
if (!pt->is_partial)
{
snprintf (status, sizeof status, "%lu", (ulong) pt->len);
write_status_text (STATUS_PLAINTEXT_LENGTH, status);
}
}
if (! nooutput)
{
err = get_output_file (pt->name, pt->namelen, pt->buf, &fname, &fp);
if (err)
goto leave;
}
if (!pt->is_partial)
{
/* We have an actual length (which might be zero). */