aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <[email protected]>2015-11-05 11:20:42 +0000
committerNeal H. Walfield <[email protected]>2015-11-05 13:16:33 +0000
commitec409e62aea6cc829299be794f9d035d033cb51b (patch)
tree751b85be355f5e858c384cd0d2d771fc7b372878
parentcommon: Add a function for copying data from one iobuf to another. (diff)
downloadgnupg-ec409e62aea6cc829299be794f9d035d033cb51b.tar.gz
gnupg-ec409e62aea6cc829299be794f9d035d033cb51b.zip
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 <[email protected]> GnuPG-bug-id: 1060 Debian-bug-id: 282061
-rw-r--r--g10/decrypt-data.c33
-rw-r--r--g10/gpg.c5
-rw-r--r--g10/options.h2
-rw-r--r--g10/packet.h2
-rw-r--r--g10/plaintext.c136
5 files changed, 130 insertions, 48 deletions
diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c
index 570a71d11..b575f39dd 100644
--- a/g10/decrypt-data.c
+++ b/g10/decrypt-data.c
@@ -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 );
- proc_packets (ctrl, procctx, ed->buf );
+ 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);
diff --git a/g10/gpg.c b/g10/gpg.c
index cdf7b0d7f..ef283b487 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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);
diff --git a/g10/options.h b/g10/options.h
index bc92dd746..c8541b2e4 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -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
diff --git a/g10/packet.h b/g10/packet.h
index 21c80f3f2..387a5b5cd 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -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,
diff --git a/g10/plaintext.c b/g10/plaintext.c
index 7929f6643..aeee2ac49 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -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)
-{
- 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
+/* Get the output filename. On success, the actual filename that is
+ used is set in *FNAMEP and a filepointer is returned in *FP.
- /* 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];
+ 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).
- /* 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);
+ DATA is the iobuf containing the input data. We just use it to get
+ the input file's filename.
- if (!pt->is_partial)
- {
- snprintf (status, sizeof status, "%lu", (ulong) pt->len);
- write_status_text (STATUS_PLAINTEXT_LENGTH, status);
- }
- }
+ 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;
+ 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). */