From abb352de51bc964c06007fce43ed6f6caea87c15 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Mon, 4 Apr 2016 17:05:50 +0200 Subject: [PATCH] g10: Support armored keyrings in gpgv. * doc/gpgv.texi: Document the feature. * g10/Makefile.am (gpgv2_SOURCES): Add dearmor.c. * g10/dearmor.c (dearmor_file): Add sink argument. * g10/gpg.c (main): Adapt accordingly. * g10/gpgv.c (make_temp_dir): New function. (main): De-armor keyrings. * g10/main.h (dearmor_file): Adapt prototype. GnuPG-bug-id: 2290 Signed-off-by: Justus Winter --- doc/gpgv.texi | 3 ++ g10/Makefile.am | 3 +- g10/dearmor.c | 7 +-- g10/gpg.c | 2 +- g10/gpgv.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++-- g10/main.h | 2 +- 6 files changed, 137 insertions(+), 10 deletions(-) diff --git a/doc/gpgv.texi b/doc/gpgv.texi index 280966bf8..fcaffbc39 100644 --- a/doc/gpgv.texi +++ b/doc/gpgv.texi @@ -100,6 +100,9 @@ are replaced by the HOME directory. If the filename does not contain a slash, it is assumed to be in the home-directory ("~/.gnupg" if --homedir is not used). +If @var{file} ends in @code{.asc} then it is assumed to be an armored +keyring produced e.g. by @code{gpg --export}. + @item --status-fd @var{n} @opindex status-fd Write special status strings to the file descriptor @var{n}. See the diff --git a/g10/Makefile.am b/g10/Makefile.am index 473a3ac99..a30bc01da 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -140,7 +140,8 @@ gpg2_SOURCES = gpg.c \ gpgcompose_SOURCES = gpgcompose.c $(gpg_sources) gpgv2_SOURCES = gpgv.c \ $(common_source) \ - verify.c + verify.c \ + dearmor.c #gpgd_SOURCES = gpgd.c \ # ks-proto.h \ diff --git a/g10/dearmor.c b/g10/dearmor.c index 3fdd57dae..3f1976f96 100644 --- a/g10/dearmor.c +++ b/g10/dearmor.c @@ -35,10 +35,11 @@ #include "i18n.h" /**************** - * Take an armor file and write it out without armor + * Take an armor file and write it out without armor. If outfd is not + * -1, the output will be written to the given file descriptor. */ int -dearmor_file( const char *fname ) +dearmor_file( const char *fname, int outfd ) { armor_filter_context_t *afx; IOBUF inp = NULL, out = NULL; @@ -64,7 +65,7 @@ dearmor_file( const char *fname ) push_armor_filter ( afx, inp ); - if( (rc = open_outfile (-1, fname, 0, 0, &out)) ) + if( (rc = open_outfile (outfd, fname, 0, 0, &out)) ) goto leave; while( (c = iobuf_get(inp)) != -1 ) diff --git a/g10/gpg.c b/g10/gpg.c index b9d69a7cb..bb5e8472d 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -4285,7 +4285,7 @@ main (int argc, char **argv) case aDeArmor: if( argc > 1 ) wrong_args("--dearmor [file]"); - rc = dearmor_file( argc? *argv: NULL ); + rc = dearmor_file( argc? *argv: NULL, -1 ); if( rc ) { write_status_failure ("dearmor", rc); diff --git a/g10/gpgv.c b/g10/gpgv.c index 19a2ff6c7..de6529b04 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -25,9 +25,7 @@ #include #include #include -#ifdef HAVE_DOSISH_SYSTEM -#include /* for setmode() */ -#endif +#include #ifdef HAVE_LIBREADLINE #define GNUPG_LIBREADLINE_H_INCLUDED #include @@ -135,6 +133,66 @@ my_strusage( int level ) } +static char * +make_temp_dir (void) +{ + char *result; + char *tmp; +#if defined (_WIN32) + int err; + + tmp = xmalloc (MAX_PATH+2); + err = GetTempPath (MAX_PATH + 1, tmp); + if (err == 0 || err > MAX_PATH + 1) + strcpy (tmp, "c:\\windows\\temp"); + else + { + int len = strlen (tmp); + + /* GetTempPath may return with \ on the end */ + while (len > 0 && tmp[len-1] == '\\') + { + tmp[len-1] = '\0'; + len--; + } + } +#else /* More unixish systems */ + tmp = getenv ("TMPDIR"); + if (tmp == NULL) + { + tmp = getenv ("TMP"); + if (tmp == NULL) + { +#ifdef __riscos__ + tmp = ".GnuPG"; + mkdir (tmp, 0700); /* Error checks occur later on */ +#else + tmp = "/tmp"; +#endif + } + } +#endif + + result = xasprintf ("%s" DIRSEP_S "gpg-XXXXXX", tmp); + +#if defined (_WIN32) + xfree(tmp); +#endif + + if (result == NULL) + return NULL; + + if (! gnupg_mkdtemp (result)) + { + log_error (_("can't create directory '%s': %s\n"), + result, strerror (errno)); + xfree (result); + return NULL; + } + + return result; +} + int main( int argc, char **argv ) @@ -143,6 +201,7 @@ main( int argc, char **argv ) int rc=0; strlist_t sl; strlist_t nrings = NULL; + strlist_t tmprings = NULL; unsigned configlineno; ctrl_t ctrl; @@ -216,8 +275,63 @@ main( int argc, char **argv ) (KEYDB_RESOURCE_FLAG_READONLY |KEYDB_RESOURCE_FLAG_GPGVDEF)); for (sl = nrings; sl; sl = sl->next) - keydb_add_resource (sl->d, KEYDB_RESOURCE_FLAG_READONLY); + { + char *name = sl->d; + if (strlen (name) >= 4 + && strcmp (&name[strlen (name) - 4], ".asc") == 0) + { + /* The file is an armored keyring. Dearmor it. */ + char *tmpdir = NULL, *tmpname = NULL; + int fd = -1, success; + tmpdir = make_temp_dir (); + if (tmpdir == NULL) + goto cleanup; + + tmpname = xasprintf ("%s" DIRSEP_S "key", tmpdir); + if (tmpname == NULL) + goto cleanup; + + if (! add_to_strlist_try (&tmprings, tmpname)) + goto cleanup; + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + fd = open (tmpname, O_WRONLY|O_CREAT|O_BINARY, S_IRUSR); + if (fd == -1) + goto cleanup; + + rc = dearmor_file (name, fd); + close (fd); + fd = -2; + if (rc) + goto cleanup; + + keydb_add_resource (tmpname, KEYDB_RESOURCE_FLAG_READONLY); + + cleanup: + success = tmpdir && tmpname && fd != -1; + if (fd >= 0) + close (fd); + if (tmpname) + { + if (! success) + unlink (tmpname); + xfree (tmpname); + } + if (tmpdir) + { + if (! success) + rmdir (tmpdir); + xfree (tmpdir); + } + if (! success) + g10_exit (1); + } + else + keydb_add_resource (name, KEYDB_RESOURCE_FLAG_READONLY); + } FREE_STRLIST (nrings); ctrl = xcalloc (1, sizeof *ctrl); @@ -227,6 +341,14 @@ main( int argc, char **argv ) xfree (ctrl); + for (sl = tmprings; sl; sl = sl->next) + { + unlink (sl->d); + sl->d[strlen (sl->d) - 4] = 0; + rmdir (sl->d); + } + FREE_STRLIST (tmprings); + /* cleanup */ g10_exit (0); return 8; /*NOTREACHED*/ diff --git a/g10/main.h b/g10/main.h index 5b5947e48..766c53fd9 100644 --- a/g10/main.h +++ b/g10/main.h @@ -389,7 +389,7 @@ gpg_error_t receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd, gpg_error_t export_ssh_key (ctrl_t ctrl, const char *userid); /*-- dearmor.c --*/ -int dearmor_file( const char *fname ); +int dearmor_file( const char *fname, int outfd ); int enarmor_file( const char *fname ); /*-- revoke.c --*/