From b841a883a2a66807aa427e65d49067584bedfbe2 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 23 Jun 2016 11:55:46 +0200 Subject: common: Rename private-keys.c to name-value.c * common/private-keys.c: Rename to name-value.c. * common/private-keys.h: Rename to name-value.h. Chage all users. * common/t-private-keys.c: Rename to t-name-value.c. * common/Makefile.am: Adjust accordingly. -- The module is cool enough to be used for other purposes as well. Thus we better change the name. Signed-off-by: Werner Koch --- common/t-name-value.c | 541 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 541 insertions(+) create mode 100644 common/t-name-value.c (limited to 'common/t-name-value.c') diff --git a/common/t-name-value.c b/common/t-name-value.c new file mode 100644 index 000000000..d6cef3503 --- /dev/null +++ b/common/t-name-value.c @@ -0,0 +1,541 @@ +/* t-name-value.c - Module test for name-value.c + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "name-value.h" + +static int verbose; + +void +test_getting_values (pkc_t pk) +{ + pke_t e; + + e = pkc_lookup (pk, "Comment:"); + assert (e); + + /* Names are case-insensitive. */ + e = pkc_lookup (pk, "comment:"); + assert (e); + e = pkc_lookup (pk, "COMMENT:"); + assert (e); + + e = pkc_lookup (pk, "SomeOtherName:"); + assert (e); +} + + +void +test_key_extraction (pkc_t pk) +{ + gpg_error_t err; + gcry_sexp_t key; + + err = pkc_get_private_key (pk, &key); + assert (err == 0); + assert (key); + + if (verbose) + gcry_sexp_dump (key); + + gcry_sexp_release (key); +} + + +void +test_iteration (pkc_t pk) +{ + int i; + pke_t e; + + i = 0; + for (e = pkc_first (pk); e; e = pke_next (e)) + i++; + assert (i == 4); + + i = 0; + for (e = pkc_lookup (pk, "Comment:"); + e; + e = pke_next_value (e, "Comment:")) + i++; + assert (i == 3); +} + + +void +test_whitespace (pkc_t pk) +{ + pke_t e; + + e = pkc_lookup (pk, "One:"); + assert (e); + assert (strcmp (pke_value (e), "WithoutWhitespace") == 0); + + e = pkc_lookup (pk, "Two:"); + assert (e); + assert (strcmp (pke_value (e), "With Whitespace") == 0); + + e = pkc_lookup (pk, "Three:"); + assert (e); + assert (strcmp (pke_value (e), + "Blank lines in continuations encode newlines.\n" + "Next paragraph.") == 0); +} + + +struct +{ + char *value; + void (*test_func) (pkc_t); +} tests[] = + { + { + "# This is a comment followed by an empty line\n" + "\n", + NULL, + }, + { + "# This is a comment followed by two empty lines, Windows style\r\n" + "\r\n" + "\r\n", + NULL, + }, + { + "# Some name,value pairs\n" + "Comment: Some comment.\n" + "SomeOtherName: Some value.\n", + test_getting_values, + }, + { + " # Whitespace is preserved as much as possible\r\n" + "Comment:Some comment.\n" + "SomeOtherName: Some value. \n", + test_getting_values, + }, + { + "# Values may be continued in the next line as indicated by leading\n" + "# space\n" + "Comment: Some rather long\n" + " comment that is continued in the next line.\n" + "\n" + " Blank lines with or without whitespace are allowed within\n" + " continuations to allow paragraphs.\n" + "SomeOtherName: Some value.\n", + test_getting_values, + }, + { + "# Names may be given multiple times forming an array of values\n" + "Comment: Some comment, element 0.\n" + "Comment: Some comment, element 1.\n" + "Comment: Some comment, element 2.\n" + "SomeOtherName: Some value.\n", + test_iteration, + }, + { + "# One whitespace at the beginning of a continuation is swallowed.\n" + "One: Without\n" + " Whitespace\n" + "Two: With\n" + " Whitespace\n" + "Three: Blank lines in continuations encode newlines.\n" + "\n" + " Next paragraph.\n", + test_whitespace, + }, + { + "Description: Key to sign all GnuPG released tarballs.\n" + " The key is actually stored on a smart card.\n" + "Use-for-ssh: yes\n" + "OpenSSH-cert: long base64 encoded string wrapped so that this\n" + " key file can be easily edited with a standard editor.\n" + "Key: (shadowed-private-key\n" + " (rsa\n" + " (n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900\n" + " 2961D8AEA153424DC851EF13B83AC64FBE365C59DC1BD3E83017C90D4365B4\n" + " 83E02859FC13DB5842A00E969480DB96CE6F7D1C03600392B8E08EF0C01FC7\n" + " 19F9F9086B25AD39B4F1C2A2DF3E2BE317110CFFF21D4A11455508FE407997\n" + " 601260816C8422297C0637BB291C3A079B9CB38A92CE9E551F80AA0EBF4F0E\n" + " 72C3F250461E4D31F23A7087857FC8438324A013634563D34EFDDCBF2EA80D\n" + " F9662C9CCD4BEF2522D8BDFED24CEF78DC6B309317407EAC576D889F88ADA0\n" + " 8C4FFB480981FB68C5C6CA27503381D41018E6CDC52AAAE46B166BDC10637A\n" + " E186A02BA2497FDC5D1221#)\n" + " (e #00010001#)\n" + " (shadowed t1-v1\n" + " (#D2760001240102000005000011730000# OPENPGP.1)\n" + " )))\n", + test_key_extraction, + }, + }; + + +static char * +pkc_to_string (pkc_t pk) +{ + gpg_error_t err; + char *buf; + size_t len; + estream_t sink; + + sink = es_fopenmem (0, "rw"); + assert (sink); + + err = pkc_write (pk, sink); + assert (err == 0); + + len = es_ftell (sink); + buf = xmalloc (len+1); + assert (buf); + + es_fseek (sink, 0, SEEK_SET); + es_read (sink, buf, len, NULL); + buf[len] = 0; + + es_fclose (sink); + return buf; +} + + +void dummy_free (void *p) { (void) p; } +void *dummy_realloc (void *p, size_t s) { (void) s; return p; } + +void +run_tests (void) +{ + gpg_error_t err; + pkc_t pk; + + int i; + for (i = 0; i < DIM (tests); i++) + { + estream_t source; + char *buf; + size_t len; + + len = strlen (tests[i].value); + source = es_mopen (tests[i].value, len, len, + 0, dummy_realloc, dummy_free, "r"); + assert (source); + + err = pkc_parse (&pk, NULL, source); + assert (err == 0); + assert (pk); + + if (verbose) + { + err = pkc_write (pk, es_stderr); + assert (err == 0); + } + + buf = pkc_to_string (pk); + assert (memcmp (tests[i].value, buf, len) == 0); + + es_fclose (source); + xfree (buf); + + if (tests[i].test_func) + tests[i].test_func (pk); + + pkc_release (pk); + } +} + + +void +run_modification_tests (void) +{ + gpg_error_t err; + pkc_t pk; + gcry_sexp_t key; + char *buf; + + pk = pkc_new (); + assert (pk); + + pkc_set (pk, "Foo:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Bar\n") == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "Baz"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\n") == 0); + xfree (buf); + + pkc_set (pk, "Bar:", "Bazzel"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_add (pk, "Foo:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_add (pk, "DontExistYet:", "Bar"); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\nDontExistYet: Bar\n") + == 0); + xfree (buf); + + pkc_delete (pk, pkc_lookup (pk, "DontExistYet:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pke_next_value (pkc_lookup (pk, "Foo:"), "Foo:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pkc_lookup (pk, "Foo:")); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Bar: Bazzel\n") == 0); + xfree (buf); + + pkc_delete (pk, pkc_first (pk)); + buf = pkc_to_string (pk); + assert (strcmp (buf, "") == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "A really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: A really long value spanning across multiple" + " lines that has to be\n wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "XA really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: XA really long value spanning across multiple" + " lines that has to\n be wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "XXXXA really long value spanning across multiple lines" + " that has to be wrapped at a convenient space."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: XXXXA really long value spanning across multiple" + " lines that has\n to be wrapped at a convenient space.\n") + == 0); + xfree (buf); + + pkc_set (pk, "Foo:", "Areallylongvaluespanningacrossmultiplelines" + "thathastobewrappedataconvenientspacethatisnotthere."); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Foo: Areallylongvaluespanningacrossmultiplelinesthat" + "hastobewrappedataco\n nvenientspacethatisnotthere.\n") + == 0); + xfree (buf); + pkc_release (pk); + + pk = pkc_new (); + assert (pk); + + err = gcry_sexp_build (&key, NULL, "(hello world)"); + assert (err == 0); + assert (key); + + err = pkc_set_private_key (pk, key); + gcry_sexp_release (key); + assert (err == 0); + buf = pkc_to_string (pk); + assert (strcmp (buf, "Key: (hello world)\n") == 0); + xfree (buf); + pkc_release (pk); +} + + +void +convert (const char *fname) +{ + gpg_error_t err; + estream_t source; + gcry_sexp_t key; + char *buf; + size_t buflen; + struct stat st; + pkc_t pk; + + source = es_fopen (fname, "rb"); + if (source == NULL) + goto leave; + + if (fstat (es_fileno (source), &st)) + goto leave; + + buflen = st.st_size; + buf = xtrymalloc (buflen+1); + assert (buf); + + if (es_fread (buf, buflen, 1, source) != 1) + goto leave; + + err = gcry_sexp_sscan (&key, NULL, buf, buflen); + if (err) + { + fprintf (stderr, "malformed s-expression in %s\n", fname); + exit (1); + } + + pk = pkc_new (); + assert (pk); + + err = pkc_set_private_key (pk, key); + assert (err == 0); + + err = pkc_write (pk, es_stdout); + assert (err == 0); + + return; + + leave: + perror (fname); + exit (1); +} + + +void +parse (const char *fname) +{ + gpg_error_t err; + estream_t source; + char *buf; + pkc_t pk_a, pk_b; + pke_t e; + int line; + + source = es_fopen (fname, "rb"); + if (source == NULL) + { + perror (fname); + exit (1); + } + + err = pkc_parse (&pk_a, &line, source); + if (err) + { + fprintf (stderr, "failed to parse %s line %d: %s\n", + fname, line, gpg_strerror (err)); + exit (1); + } + + buf = pkc_to_string (pk_a); + xfree (buf); + + pk_b = pkc_new (); + assert (pk_b); + + for (e = pkc_first (pk_a); e; e = pke_next (e)) + { + gcry_sexp_t key = NULL; + + if (strcasecmp (pke_name (e), "Key:") == 0) + { + err = pkc_get_private_key (pk_a, &key); + if (err) + key = NULL; + } + + if (key) + { + err = pkc_set_private_key (pk_b, key); + assert (err == 0); + } + else + { + err = pkc_add (pk_b, pke_name (e), pke_value (e)); + assert (err == 0); + } + } + + buf = pkc_to_string (pk_b); + if (verbose) + fprintf (stdout, "%s", buf); + xfree (buf); +} + + +void +print_usage (void) +{ + fprintf (stderr, + "usage: t-private-keys [--verbose]" + " [--convert " + " || --parse ]\n"); + exit (2); +} + + +int +main (int argc, char **argv) +{ + enum { TEST, CONVERT, PARSE } command = TEST; + + if (argc) + { argc--; argv++; } + if (argc && !strcmp (argv[0], "--verbose")) + { + verbose = 1; + argc--; argv++; + } + + if (argc && !strcmp (argv[0], "--convert")) + { + command = CONVERT; + argc--; argv++; + if (argc != 1) + print_usage (); + } + + if (argc && !strcmp (argv[0], "--parse")) + { + command = PARSE; + argc--; argv++; + if (argc != 1) + print_usage (); + } + + switch (command) + { + case TEST: + run_tests (); + run_modification_tests (); + break; + + case CONVERT: + convert (*argv); + break; + + case PARSE: + parse (*argv); + break; + } + + return 0; +} -- cgit From d74d23d860c1e5039bd595c31c846782c5cb8025 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 23 Jun 2016 12:12:50 +0200 Subject: common: Rename external symbols in name-value.c. * common/name-value.c, common/name-value.h: Rename symbol prefixes from "pkc_" to "nvc_" and from "pke_" to "nve_". Change all callers. Signed-off-by: Werner Koch --- agent/findkey.c | 18 +++--- common/name-value.c | 106 +++++++++++++++++----------------- common/name-value.h | 38 ++++++------- common/t-name-value.c | 154 +++++++++++++++++++++++++------------------------- 4 files changed, 158 insertions(+), 158 deletions(-) (limited to 'common/t-name-value.c') diff --git a/agent/findkey.c b/agent/findkey.c index b2215101a..dc7099c76 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -57,12 +57,12 @@ write_extended_private_key (char *fname, estream_t fp, const void *buf, size_t len) { gpg_error_t err; - pkc_t pk = NULL; + nvc_t pk = NULL; gcry_sexp_t key = NULL; int remove = 0; int line; - err = pkc_parse (&pk, &line, fp); + err = nvc_parse (&pk, &line, fp); if (err) { log_error ("error parsing '%s' line %d: %s\n", @@ -74,7 +74,7 @@ write_extended_private_key (char *fname, estream_t fp, if (err) goto leave; - err = pkc_set_private_key (pk, key); + err = nvc_set_private_key (pk, key); if (err) goto leave; @@ -82,7 +82,7 @@ write_extended_private_key (char *fname, estream_t fp, if (err) goto leave; - err = pkc_write (pk, fp); + err = nvc_write (pk, fp); if (err) { log_error ("error writing '%s': %s\n", fname, gpg_strerror (err)); @@ -117,7 +117,7 @@ write_extended_private_key (char *fname, estream_t fp, gnupg_remove (fname); xfree (fname); gcry_sexp_release (key); - pkc_release (pk); + nvc_release (pk); return err; } @@ -687,10 +687,10 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) if (first != '(') { /* Key is in extended format. */ - pkc_t pk; + nvc_t pk; int line; - rc = pkc_parse (&pk, &line, fp); + rc = nvc_parse (&pk, &line, fp); es_fclose (fp); if (rc) @@ -698,8 +698,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) fname, line, gpg_strerror (rc)); else { - rc = pkc_get_private_key (pk, result); - pkc_release (pk); + rc = nvc_get_private_key (pk, result); + nvc_release (pk); if (rc) log_error ("error getting private key from '%s': %s\n", fname, gpg_strerror (rc)); diff --git a/common/name-value.c b/common/name-value.c index 601ddd43b..e297f1a54 100644 --- a/common/name-value.c +++ b/common/name-value.c @@ -43,17 +43,17 @@ #include "util.h" #include "name-value.h" -struct private_key_container +struct name_value_container { - struct private_key_entry *first; - struct private_key_entry *last; + struct name_value_entry *first; + struct name_value_entry *last; }; -struct private_key_entry +struct name_value_entry { - struct private_key_entry *prev; - struct private_key_entry *next; + struct name_value_entry *prev; + struct name_value_entry *next; /* The name. Comments and blank lines have NAME set to NULL. */ char *name; @@ -80,15 +80,15 @@ my_error_from_syserror (void) /* Allocation and deallocation. */ /* Allocate a private key container structure. */ -pkc_t -pkc_new (void) +nvc_t +nvc_new (void) { - return xtrycalloc (1, sizeof (struct private_key_container)); + return xtrycalloc (1, sizeof (struct name_value_container)); } static void -pke_release (pke_t entry) +nve_release (nve_t entry) { if (entry == NULL) return; @@ -104,9 +104,9 @@ pke_release (pke_t entry) /* Release a private key container structure. */ void -pkc_release (pkc_t pk) +nvc_release (nvc_t pk) { - pke_t e, next; + nve_t e, next; if (pk == NULL) return; @@ -114,7 +114,7 @@ pkc_release (pkc_t pk) for (e = pk->first; e; e = next) { next = e->next; - pke_release (e); + nve_release (e); } xfree (pk); @@ -145,7 +145,7 @@ valid_name (const char *name) /* Makes sure that ENTRY has a RAW_VALUE. */ static gpg_error_t -assert_raw_value (pke_t entry) +assert_raw_value (nve_t entry) { gpg_error_t err = 0; size_t len, offset; @@ -261,7 +261,7 @@ continuation_length (const char *s, int *swallow_ws, const char **start) /* Makes sure that ENTRY has a VALUE. */ static gpg_error_t -assert_value (pke_t entry) +assert_value (nve_t entry) { size_t len; int swallow_ws; @@ -302,7 +302,7 @@ assert_value (pke_t entry) /* Get the name. */ char * -pke_name (pke_t pke) +nve_name (nve_t pke) { return pke->name; } @@ -310,7 +310,7 @@ pke_name (pke_t pke) /* Get the value. */ char * -pke_value (pke_t pke) +nve_value (nve_t pke) { if (assert_value (pke)) return NULL; @@ -326,11 +326,11 @@ pke_value (pke_t pke) given. If PRESERVE_ORDER is not given, entries with the same name are grouped. NAME, VALUE and RAW_VALUE is consumed. */ static gpg_error_t -_pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value, +_nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value, int preserve_order) { gpg_error_t err = 0; - pke_t e; + nve_t e; assert (value || raw_value); @@ -340,7 +340,7 @@ _pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value, goto leave; } - if (name && ascii_strcasecmp (name, "Key:") == 0 && pkc_lookup (pk, "Key:")) + if (name && ascii_strcasecmp (name, "Key:") == 0 && nvc_lookup (pk, "Key:")) { err = gpg_error (GPG_ERR_INV_NAME); goto leave; @@ -359,21 +359,21 @@ _pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value, if (pk->first) { - pke_t last; + nve_t last; if (preserve_order || name == NULL) last = pk->last; else { /* See if there is already an entry with NAME. */ - last = pkc_lookup (pk, name); + last = nvc_lookup (pk, name); /* If so, find the last in that block. */ if (last) { while (last->next) { - pke_t next = last->next; + nve_t next = last->next; if (next->name && ascii_strcasecmp (next->name, name) == 0) last = next; @@ -419,7 +419,7 @@ _pkc_add (pkc_t pk, char *name, char *value, strlist_t raw_value, /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it is not updated but the new entry is appended. */ gpg_error_t -pkc_add (pkc_t pk, const char *name, const char *value) +nvc_add (nvc_t pk, const char *name, const char *value) { char *k, *v; @@ -434,7 +434,7 @@ pkc_add (pkc_t pk, const char *name, const char *value) return my_error_from_syserror (); } - return _pkc_add (pk, k, v, NULL, 0); + return _nvc_add (pk, k, v, NULL, 0); } @@ -442,14 +442,14 @@ pkc_add (pkc_t pk, const char *name, const char *value) is updated with VALUE. If multiple entries with NAME exist, the first entry is updated. */ gpg_error_t -pkc_set (pkc_t pk, const char *name, const char *value) +nvc_set (nvc_t pk, const char *name, const char *value) { - pke_t e; + nve_t e; if (! valid_name (name)) return GPG_ERR_INV_NAME; - e = pkc_lookup (pk, name); + e = nvc_lookup (pk, name); if (e) { char *v; @@ -468,13 +468,13 @@ pkc_set (pkc_t pk, const char *name, const char *value) return 0; } else - return pkc_add (pk, name, value); + return nvc_add (pk, name, value); } /* Delete the given entry from PK. */ void -pkc_delete (pkc_t pk, pke_t entry) +nvc_delete (nvc_t pk, nve_t entry) { if (entry->prev) entry->prev->next = entry->next; @@ -486,7 +486,7 @@ pkc_delete (pkc_t pk, pke_t entry) else pk->last = entry->prev; - pke_release (entry); + nve_release (entry); } @@ -494,10 +494,10 @@ pkc_delete (pkc_t pk, pke_t entry) /* Lookup and iteration. */ /* Get the first non-comment entry. */ -pke_t -pkc_first (pkc_t pk) +nve_t +nvc_first (nvc_t pk) { - pke_t entry; + nve_t entry; for (entry = pk->first; entry; entry = entry->next) if (entry->name) return entry; @@ -506,10 +506,10 @@ pkc_first (pkc_t pk) /* Get the first entry with the given name. */ -pke_t -pkc_lookup (pkc_t pk, const char *name) +nve_t +nvc_lookup (nvc_t pk, const char *name) { - pke_t entry; + nve_t entry; for (entry = pk->first; entry; entry = entry->next) if (entry->name && ascii_strcasecmp (entry->name, name) == 0) return entry; @@ -518,8 +518,8 @@ pkc_lookup (pkc_t pk, const char *name) /* Get the next non-comment entry. */ -pke_t -pke_next (pke_t entry) +nve_t +nve_next (nve_t entry) { for (entry = entry->next; entry; entry = entry->next) if (entry->name) @@ -529,8 +529,8 @@ pke_next (pke_t entry) /* Get the next entry with the given name. */ -pke_t -pke_next_value (pke_t entry, const char *name) +nve_t +nve_next_value (nve_t entry, const char *name) { for (entry = entry->next; entry; entry = entry->next) if (entry->name && ascii_strcasecmp (entry->name, name) == 0) @@ -544,12 +544,12 @@ pke_next_value (pke_t entry, const char *name) /* Get the private key. */ gpg_error_t -pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp) +nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp) { gpg_error_t err; - pke_t e; + nve_t e; - e = pkc_lookup (pk, "Key:"); + e = nvc_lookup (pk, "Key:"); if (e == NULL) return gpg_error (GPG_ERR_MISSING_KEY); @@ -563,7 +563,7 @@ pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp) /* Set the private key. */ gpg_error_t -pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp) +nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp) { gpg_error_t err; char *raw, *clean, *p; @@ -610,7 +610,7 @@ pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp) } *p = 0; - err = pkc_set (pk, "Key:", clean); + err = nvc_set (pk, "Key:", clean); xfree (raw); xfree (clean); return err; @@ -624,7 +624,7 @@ pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp) structure in RESULT. If ERRLINEP is given, the line number the parser was last considering is stored there. */ gpg_error_t -pkc_parse (pkc_t *result, int *errlinep, estream_t stream) +nvc_parse (nvc_t *result, int *errlinep, estream_t stream) { gpg_error_t err = 0; gpgrt_ssize_t len; @@ -634,7 +634,7 @@ pkc_parse (pkc_t *result, int *errlinep, estream_t stream) strlist_t raw_value = NULL; - *result = pkc_new (); + *result = nvc_new (); if (*result == NULL) return my_error_from_syserror (); @@ -664,7 +664,7 @@ pkc_parse (pkc_t *result, int *errlinep, estream_t stream) /* No continuation. Add the current entry if any. */ if (raw_value) { - err = _pkc_add (*result, name, NULL, raw_value, 1); + err = _nvc_add (*result, name, NULL, raw_value, 1); if (err) goto leave; } @@ -713,13 +713,13 @@ pkc_parse (pkc_t *result, int *errlinep, estream_t stream) /* Add the final entry. */ if (raw_value) - err = _pkc_add (*result, name, NULL, raw_value, 1); + err = _nvc_add (*result, name, NULL, raw_value, 1); leave: gpgrt_free (buf); if (err) { - pkc_release (*result); + nvc_release (*result); *result = NULL; } @@ -729,10 +729,10 @@ pkc_parse (pkc_t *result, int *errlinep, estream_t stream) /* Write a representation of PK to STREAM. */ gpg_error_t -pkc_write (pkc_t pk, estream_t stream) +nvc_write (nvc_t pk, estream_t stream) { gpg_error_t err; - pke_t entry; + nve_t entry; strlist_t s; for (entry = pk->first; entry; entry = entry->next) diff --git a/common/name-value.h b/common/name-value.h index 0a8694a57..21a5293e0 100644 --- a/common/name-value.h +++ b/common/name-value.h @@ -30,43 +30,43 @@ #ifndef GNUPG_COMMON_NAME_VALUE_H #define GNUPG_COMMON_NAME_VALUE_H -struct private_key_container; -typedef struct private_key_container *pkc_t; +struct name_value_container; +typedef struct name_value_container *nvc_t; -struct private_key_entry; -typedef struct private_key_entry *pke_t; +struct name_value_entry; +typedef struct name_value_entry *nve_t; /* Memory management, and dealing with entries. */ /* Allocate a private key container structure. */ -pkc_t pkc_new (void); +nvc_t nvc_new (void); /* Release a private key container structure. */ -void pkc_release (pkc_t pk); +void nvc_release (nvc_t pk); /* Get the name. */ -char *pke_name (pke_t pke); +char *nve_name (nve_t pke); /* Get the value. */ -char *pke_value (pke_t pke); +char *nve_value (nve_t pke); /* Lookup and iteration. */ /* Get the first non-comment entry. */ -pke_t pkc_first (pkc_t pk); +nve_t nvc_first (nvc_t pk); /* Get the first entry with the given name. */ -pke_t pkc_lookup (pkc_t pk, const char *name); +nve_t nvc_lookup (nvc_t pk, const char *name); /* Get the next non-comment entry. */ -pke_t pke_next (pke_t entry); +nve_t nve_next (nve_t entry); /* Get the next entry with the given name. */ -pke_t pke_next_value (pke_t entry, const char *name); +nve_t nve_next_value (nve_t entry, const char *name); @@ -74,25 +74,25 @@ pke_t pke_next_value (pke_t entry, const char *name); /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it is not updated but the new entry is appended. */ -gpg_error_t pkc_add (pkc_t pk, const char *name, const char *value); +gpg_error_t nvc_add (nvc_t pk, const char *name, const char *value); /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it is updated with VALUE. If multiple entries with NAME exist, the first entry is updated. */ -gpg_error_t pkc_set (pkc_t pk, const char *name, const char *value); +gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value); /* Delete the given entry from PK. */ -void pkc_delete (pkc_t pk, pke_t pke); +void nvc_delete (nvc_t pk, nve_t pke); /* Private key handling. */ /* Get the private key. */ -gpg_error_t pkc_get_private_key (pkc_t pk, gcry_sexp_t *retsexp); +gpg_error_t nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp); /* Set the private key. */ -gpg_error_t pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp); +gpg_error_t nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp); @@ -101,9 +101,9 @@ gpg_error_t pkc_set_private_key (pkc_t pk, gcry_sexp_t sexp); /* Parse STREAM and return a newly allocated private key container structure in RESULT. If ERRLINEP is given, the line number the parser was last considering is stored there. */ -gpg_error_t pkc_parse (pkc_t *result, int *errlinep, estream_t stream); +gpg_error_t nvc_parse (nvc_t *result, int *errlinep, estream_t stream); /* Write a representation of PK to STREAM. */ -gpg_error_t pkc_write (pkc_t pk, estream_t stream); +gpg_error_t nvc_write (nvc_t pk, estream_t stream); #endif /* GNUPG_COMMON_NAME_VALUE_H */ diff --git a/common/t-name-value.c b/common/t-name-value.c index d6cef3503..810c85c38 100644 --- a/common/t-name-value.c +++ b/common/t-name-value.c @@ -31,31 +31,31 @@ static int verbose; void -test_getting_values (pkc_t pk) +test_getting_values (nvc_t pk) { - pke_t e; + nve_t e; - e = pkc_lookup (pk, "Comment:"); + e = nvc_lookup (pk, "Comment:"); assert (e); /* Names are case-insensitive. */ - e = pkc_lookup (pk, "comment:"); + e = nvc_lookup (pk, "comment:"); assert (e); - e = pkc_lookup (pk, "COMMENT:"); + e = nvc_lookup (pk, "COMMENT:"); assert (e); - e = pkc_lookup (pk, "SomeOtherName:"); + e = nvc_lookup (pk, "SomeOtherName:"); assert (e); } void -test_key_extraction (pkc_t pk) +test_key_extraction (nvc_t pk) { gpg_error_t err; gcry_sexp_t key; - err = pkc_get_private_key (pk, &key); + err = nvc_get_private_key (pk, &key); assert (err == 0); assert (key); @@ -67,41 +67,41 @@ test_key_extraction (pkc_t pk) void -test_iteration (pkc_t pk) +test_iteration (nvc_t pk) { int i; - pke_t e; + nve_t e; i = 0; - for (e = pkc_first (pk); e; e = pke_next (e)) + for (e = nvc_first (pk); e; e = nve_next (e)) i++; assert (i == 4); i = 0; - for (e = pkc_lookup (pk, "Comment:"); + for (e = nvc_lookup (pk, "Comment:"); e; - e = pke_next_value (e, "Comment:")) + e = nve_next_value (e, "Comment:")) i++; assert (i == 3); } void -test_whitespace (pkc_t pk) +test_whitespace (nvc_t pk) { - pke_t e; + nve_t e; - e = pkc_lookup (pk, "One:"); + e = nvc_lookup (pk, "One:"); assert (e); - assert (strcmp (pke_value (e), "WithoutWhitespace") == 0); + assert (strcmp (nve_value (e), "WithoutWhitespace") == 0); - e = pkc_lookup (pk, "Two:"); + e = nvc_lookup (pk, "Two:"); assert (e); - assert (strcmp (pke_value (e), "With Whitespace") == 0); + assert (strcmp (nve_value (e), "With Whitespace") == 0); - e = pkc_lookup (pk, "Three:"); + e = nvc_lookup (pk, "Three:"); assert (e); - assert (strcmp (pke_value (e), + assert (strcmp (nve_value (e), "Blank lines in continuations encode newlines.\n" "Next paragraph.") == 0); } @@ -110,7 +110,7 @@ test_whitespace (pkc_t pk) struct { char *value; - void (*test_func) (pkc_t); + void (*test_func) (nvc_t); } tests[] = { { @@ -193,7 +193,7 @@ struct static char * -pkc_to_string (pkc_t pk) +nvc_to_string (nvc_t pk) { gpg_error_t err; char *buf; @@ -203,7 +203,7 @@ pkc_to_string (pkc_t pk) sink = es_fopenmem (0, "rw"); assert (sink); - err = pkc_write (pk, sink); + err = nvc_write (pk, sink); assert (err == 0); len = es_ftell (sink); @@ -226,7 +226,7 @@ void run_tests (void) { gpg_error_t err; - pkc_t pk; + nvc_t pk; int i; for (i = 0; i < DIM (tests); i++) @@ -240,17 +240,17 @@ run_tests (void) 0, dummy_realloc, dummy_free, "r"); assert (source); - err = pkc_parse (&pk, NULL, source); + err = nvc_parse (&pk, NULL, source); assert (err == 0); assert (pk); if (verbose) { - err = pkc_write (pk, es_stderr); + err = nvc_write (pk, es_stderr); assert (err == 0); } - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (memcmp (tests[i].value, buf, len) == 0); es_fclose (source); @@ -259,7 +259,7 @@ run_tests (void) if (tests[i].test_func) tests[i].test_func (pk); - pkc_release (pk); + nvc_release (pk); } } @@ -268,106 +268,106 @@ void run_modification_tests (void) { gpg_error_t err; - pkc_t pk; + nvc_t pk; gcry_sexp_t key; char *buf; - pk = pkc_new (); + pk = nvc_new (); assert (pk); - pkc_set (pk, "Foo:", "Bar"); - buf = pkc_to_string (pk); + nvc_set (pk, "Foo:", "Bar"); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Bar\n") == 0); xfree (buf); - pkc_set (pk, "Foo:", "Baz"); - buf = pkc_to_string (pk); + nvc_set (pk, "Foo:", "Baz"); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\n") == 0); xfree (buf); - pkc_set (pk, "Bar:", "Bazzel"); - buf = pkc_to_string (pk); + nvc_set (pk, "Bar:", "Bazzel"); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); xfree (buf); - pkc_add (pk, "Foo:", "Bar"); - buf = pkc_to_string (pk); + nvc_add (pk, "Foo:", "Bar"); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); xfree (buf); - pkc_add (pk, "DontExistYet:", "Bar"); - buf = pkc_to_string (pk); + nvc_add (pk, "DontExistYet:", "Bar"); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\nDontExistYet: Bar\n") == 0); xfree (buf); - pkc_delete (pk, pkc_lookup (pk, "DontExistYet:")); - buf = pkc_to_string (pk); + nvc_delete (pk, nvc_lookup (pk, "DontExistYet:")); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\nFoo: Bar\nBar: Bazzel\n") == 0); xfree (buf); - pkc_delete (pk, pke_next_value (pkc_lookup (pk, "Foo:"), "Foo:")); - buf = pkc_to_string (pk); + nvc_delete (pk, nve_next_value (nvc_lookup (pk, "Foo:"), "Foo:")); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Baz\nBar: Bazzel\n") == 0); xfree (buf); - pkc_delete (pk, pkc_lookup (pk, "Foo:")); - buf = pkc_to_string (pk); + nvc_delete (pk, nvc_lookup (pk, "Foo:")); + buf = nvc_to_string (pk); assert (strcmp (buf, "Bar: Bazzel\n") == 0); xfree (buf); - pkc_delete (pk, pkc_first (pk)); - buf = pkc_to_string (pk); + nvc_delete (pk, nvc_first (pk)); + buf = nvc_to_string (pk); assert (strcmp (buf, "") == 0); xfree (buf); - pkc_set (pk, "Foo:", "A really long value spanning across multiple lines" + nvc_set (pk, "Foo:", "A really long value spanning across multiple lines" " that has to be wrapped at a convenient space."); - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: A really long value spanning across multiple" " lines that has to be\n wrapped at a convenient space.\n") == 0); xfree (buf); - pkc_set (pk, "Foo:", "XA really long value spanning across multiple lines" + nvc_set (pk, "Foo:", "XA really long value spanning across multiple lines" " that has to be wrapped at a convenient space."); - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: XA really long value spanning across multiple" " lines that has to\n be wrapped at a convenient space.\n") == 0); xfree (buf); - pkc_set (pk, "Foo:", "XXXXA really long value spanning across multiple lines" + nvc_set (pk, "Foo:", "XXXXA really long value spanning across multiple lines" " that has to be wrapped at a convenient space."); - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: XXXXA really long value spanning across multiple" " lines that has\n to be wrapped at a convenient space.\n") == 0); xfree (buf); - pkc_set (pk, "Foo:", "Areallylongvaluespanningacrossmultiplelines" + nvc_set (pk, "Foo:", "Areallylongvaluespanningacrossmultiplelines" "thathastobewrappedataconvenientspacethatisnotthere."); - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (strcmp (buf, "Foo: Areallylongvaluespanningacrossmultiplelinesthat" "hastobewrappedataco\n nvenientspacethatisnotthere.\n") == 0); xfree (buf); - pkc_release (pk); + nvc_release (pk); - pk = pkc_new (); + pk = nvc_new (); assert (pk); err = gcry_sexp_build (&key, NULL, "(hello world)"); assert (err == 0); assert (key); - err = pkc_set_private_key (pk, key); + err = nvc_set_private_key (pk, key); gcry_sexp_release (key); assert (err == 0); - buf = pkc_to_string (pk); + buf = nvc_to_string (pk); assert (strcmp (buf, "Key: (hello world)\n") == 0); xfree (buf); - pkc_release (pk); + nvc_release (pk); } @@ -380,7 +380,7 @@ convert (const char *fname) char *buf; size_t buflen; struct stat st; - pkc_t pk; + nvc_t pk; source = es_fopen (fname, "rb"); if (source == NULL) @@ -403,13 +403,13 @@ convert (const char *fname) exit (1); } - pk = pkc_new (); + pk = nvc_new (); assert (pk); - err = pkc_set_private_key (pk, key); + err = nvc_set_private_key (pk, key); assert (err == 0); - err = pkc_write (pk, es_stdout); + err = nvc_write (pk, es_stdout); assert (err == 0); return; @@ -426,8 +426,8 @@ parse (const char *fname) gpg_error_t err; estream_t source; char *buf; - pkc_t pk_a, pk_b; - pke_t e; + nvc_t pk_a, pk_b; + nve_t e; int line; source = es_fopen (fname, "rb"); @@ -437,7 +437,7 @@ parse (const char *fname) exit (1); } - err = pkc_parse (&pk_a, &line, source); + err = nvc_parse (&pk_a, &line, source); if (err) { fprintf (stderr, "failed to parse %s line %d: %s\n", @@ -445,36 +445,36 @@ parse (const char *fname) exit (1); } - buf = pkc_to_string (pk_a); + buf = nvc_to_string (pk_a); xfree (buf); - pk_b = pkc_new (); + pk_b = nvc_new (); assert (pk_b); - for (e = pkc_first (pk_a); e; e = pke_next (e)) + for (e = nvc_first (pk_a); e; e = nve_next (e)) { gcry_sexp_t key = NULL; - if (strcasecmp (pke_name (e), "Key:") == 0) + if (strcasecmp (nve_name (e), "Key:") == 0) { - err = pkc_get_private_key (pk_a, &key); + err = nvc_get_private_key (pk_a, &key); if (err) key = NULL; } if (key) { - err = pkc_set_private_key (pk_b, key); + err = nvc_set_private_key (pk_b, key); assert (err == 0); } else { - err = pkc_add (pk_b, pke_name (e), pke_value (e)); + err = nvc_add (pk_b, nve_name (e), nve_value (e)); assert (err == 0); } } - buf = pkc_to_string (pk_b); + buf = nvc_to_string (pk_b); if (verbose) fprintf (stdout, "%s", buf); xfree (buf); -- cgit From 3ead21da80da4570e77036cc05303914c9b1f364 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 23 Jun 2016 13:17:25 +0200 Subject: common: Add dedicated private key functions to name-value.c. * common/name-value.c (struct name_value_container): Add field 'private_key_mode'. (my_error): New. Use instead of gpg_error. (nvc_new_private_key): New. (nve_release): Add arg 'private_key_mode'. (nvc_release): Call nve_release with private_key_mode flag. (nvc_delete): Ditto. (_nvc_add): Do no special case "Key:" in non-private_key_mode. (nvc_get_private_key): Return error in non-private_key_mode. (nvc_set_private_key): Ditto. (nvc_parse): Factor all code out to ... (do_nvc_parse): new. Add arg 'for_private_key'. (nvc_parse_private_key): New. * agent/findkey.c (write_extended_private_key): Replace nvc_parse by nvc_parse_private_key. (read_key_file): Ditto. * common/t-name-value.c (private_key_mode): New variable. (my_nvc_new): New. Replace all callers. (test_key_extraction): Take mode in account. (run_tests): Ditto. (run_modification_tests): Ditto. (parse): Ditto. (main): Add option --parse and rename --parse to --parse-key. -- Signed-off-by: Werner Koch --- agent/findkey.c | 4 +-- common/name-value.c | 82 +++++++++++++++++++++++++++++++++---------- common/name-value.h | 15 ++++++-- common/t-name-value.c | 96 +++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 153 insertions(+), 44 deletions(-) (limited to 'common/t-name-value.c') diff --git a/agent/findkey.c b/agent/findkey.c index dc7099c76..c5ab0e905 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -62,7 +62,7 @@ write_extended_private_key (char *fname, estream_t fp, int remove = 0; int line; - err = nvc_parse (&pk, &line, fp); + err = nvc_parse_private_key (&pk, &line, fp); if (err) { log_error ("error parsing '%s' line %d: %s\n", @@ -690,7 +690,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result) nvc_t pk; int line; - rc = nvc_parse (&pk, &line, fp); + rc = nvc_parse_private_key (&pk, &line, fp); es_fclose (fp); if (rc) diff --git a/common/name-value.c b/common/name-value.c index e297f1a54..0b32a4442 100644 --- a/common/name-value.c +++ b/common/name-value.c @@ -47,6 +47,7 @@ struct name_value_container { struct name_value_entry *first; struct name_value_entry *last; + unsigned int private_key_mode:1; }; @@ -75,6 +76,13 @@ my_error_from_syserror (void) } +static inline gpg_error_t +my_error (gpg_err_code_t ec) +{ + return gpg_err_make (default_errsource, ec); +} + + /* Allocation and deallocation. */ @@ -87,17 +95,31 @@ nvc_new (void) } +/* Allocate a private key container structure for use with private keys. */ +nvc_t +nvc_new_private_key (void) +{ + nvc_t nvc = nvc_new (); + if (nvc) + nvc->private_key_mode = 1; + return nvc; +} + + static void -nve_release (nve_t entry) +nve_release (nve_t entry, int private_key_mode) { if (entry == NULL) return; xfree (entry->name); - if (entry->value) + if (entry->value && private_key_mode) wipememory (entry->value, strlen (entry->value)); xfree (entry->value); - free_strlist_wipe (entry->raw_value); + if (private_key_mode) + free_strlist_wipe (entry->raw_value); + else + free_strlist (entry->raw_value); xfree (entry); } @@ -114,7 +136,7 @@ nvc_release (nvc_t pk) for (e = pk->first; e; e = next) { next = e->next; - nve_release (e); + nve_release (e, pk->private_key_mode); } xfree (pk); @@ -336,13 +358,16 @@ _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value, if (name && ! valid_name (name)) { - err = gpg_error (GPG_ERR_INV_NAME); + err = my_error (GPG_ERR_INV_NAME); goto leave; } - if (name && ascii_strcasecmp (name, "Key:") == 0 && nvc_lookup (pk, "Key:")) + if (name + && pk->private_key_mode + && !ascii_strcasecmp (name, "Key:") + && nvc_lookup (pk, "Key:")) { - err = gpg_error (GPG_ERR_INV_NAME); + err = my_error (GPG_ERR_INV_NAME); goto leave; } @@ -486,7 +511,7 @@ nvc_delete (nvc_t pk, nve_t entry) else pk->last = entry->prev; - nve_release (entry); + nve_release (entry, pk->private_key_mode); } @@ -549,9 +574,9 @@ nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp) gpg_error_t err; nve_t e; - e = nvc_lookup (pk, "Key:"); + e = pk->private_key_mode? nvc_lookup (pk, "Key:") : NULL; if (e == NULL) - return gpg_error (GPG_ERR_MISSING_KEY); + return my_error (GPG_ERR_MISSING_KEY); err = assert_value (e); if (err) @@ -569,6 +594,9 @@ nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp) char *raw, *clean, *p; size_t len, i; + if (!pk->private_key_mode) + return my_error (GPG_ERR_MISSING_KEY); + len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0); raw = xtrymalloc (len); @@ -620,11 +648,9 @@ nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp) /* Parsing and serialization. */ -/* Parse STREAM and return a newly allocated private key container - structure in RESULT. If ERRLINEP is given, the line number the - parser was last considering is stored there. */ -gpg_error_t -nvc_parse (nvc_t *result, int *errlinep, estream_t stream) +static gpg_error_t +do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream, + int for_private_key) { gpg_error_t err = 0; gpgrt_ssize_t len; @@ -633,8 +659,7 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream) char *name = NULL; strlist_t raw_value = NULL; - - *result = nvc_new (); + *result = for_private_key? nvc_new_private_key () : nvc_new (); if (*result == NULL) return my_error_from_syserror (); @@ -680,7 +705,7 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream) colon = strchr (buf, ':'); if (colon == NULL) { - err = gpg_error (GPG_ERR_INV_VALUE); + err = my_error (GPG_ERR_INV_VALUE); goto leave; } @@ -727,6 +752,27 @@ nvc_parse (nvc_t *result, int *errlinep, estream_t stream) } +/* Parse STREAM and return a newly allocated name value container + structure in RESULT. If ERRLINEP is given, the line number the + parser was last considering is stored there. */ +gpg_error_t +nvc_parse (nvc_t *result, int *errlinep, estream_t stream) +{ + return do_nvc_parse (result, errlinep, stream, 0); +} + + +/* Parse STREAM and return a newly allocated name value container + structure in RESULT - assuming the extended private key format. If + ERRLINEP is given, the line number the parser was last considering + is stored there. */ +gpg_error_t +nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream) +{ + return do_nvc_parse (result, errlinep, stream, 1); +} + + /* Write a representation of PK to STREAM. */ gpg_error_t nvc_write (nvc_t pk, estream_t stream) diff --git a/common/name-value.h b/common/name-value.h index 21a5293e0..f5f17e6de 100644 --- a/common/name-value.h +++ b/common/name-value.h @@ -40,10 +40,14 @@ typedef struct name_value_entry *nve_t; /* Memory management, and dealing with entries. */ -/* Allocate a private key container structure. */ +/* Allocate a name value container structure. */ nvc_t nvc_new (void); -/* Release a private key container structure. */ +/* Allocate a name value container structure for use with the extended + * private key format. */ +nvc_t nvc_new_private_key (void); + +/* Release a name value container structure. */ void nvc_release (nvc_t pk); /* Get the name. */ @@ -103,6 +107,13 @@ gpg_error_t nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp); parser was last considering is stored there. */ gpg_error_t nvc_parse (nvc_t *result, int *errlinep, estream_t stream); +/* Parse STREAM and return a newly allocated name value container + structure in RESULT - assuming the extended private key format. If + ERRLINEP is given, the line number the parser was last considering + is stored there. */ +gpg_error_t nvc_parse_private_key (nvc_t *result, int *errlinep, + estream_t stream); + /* Write a representation of PK to STREAM. */ gpg_error_t nvc_write (nvc_t pk, estream_t stream); diff --git a/common/t-name-value.c b/common/t-name-value.c index 810c85c38..fc9303bb8 100644 --- a/common/t-name-value.c +++ b/common/t-name-value.c @@ -29,6 +29,18 @@ #include "name-value.h" static int verbose; +static int private_key_mode; + + +static nvc_t +my_nvc_new (void) +{ + if (private_key_mode) + return nvc_new_private_key (); + else + return nvc_new (); +} + void test_getting_values (nvc_t pk) @@ -55,14 +67,22 @@ test_key_extraction (nvc_t pk) gpg_error_t err; gcry_sexp_t key; - err = nvc_get_private_key (pk, &key); - assert (err == 0); - assert (key); + if (private_key_mode) + { + err = nvc_get_private_key (pk, &key); + assert (err == 0); + assert (key); - if (verbose) - gcry_sexp_dump (key); + if (verbose) + gcry_sexp_dump (key); - gcry_sexp_release (key); + gcry_sexp_release (key); + } + else + { + err = nvc_get_private_key (pk, &key); + assert (gpg_err_code (err) == GPG_ERR_MISSING_KEY); + } } @@ -240,7 +260,10 @@ run_tests (void) 0, dummy_realloc, dummy_free, "r"); assert (source); - err = nvc_parse (&pk, NULL, source); + if (private_key_mode) + err = nvc_parse_private_key (&pk, NULL, source); + else + err = nvc_parse (&pk, NULL, source); assert (err == 0); assert (pk); @@ -272,7 +295,7 @@ run_modification_tests (void) gcry_sexp_t key; char *buf; - pk = nvc_new (); + pk = my_nvc_new (); assert (pk); nvc_set (pk, "Foo:", "Bar"); @@ -354,20 +377,29 @@ run_modification_tests (void) xfree (buf); nvc_release (pk); - pk = nvc_new (); + pk = my_nvc_new (); assert (pk); err = gcry_sexp_build (&key, NULL, "(hello world)"); assert (err == 0); assert (key); - err = nvc_set_private_key (pk, key); - gcry_sexp_release (key); - assert (err == 0); - buf = nvc_to_string (pk); - assert (strcmp (buf, "Key: (hello world)\n") == 0); - xfree (buf); - nvc_release (pk); + if (private_key_mode) + { + err = nvc_set_private_key (pk, key); + gcry_sexp_release (key); + assert (err == 0); + + buf = nvc_to_string (pk); + assert (strcmp (buf, "Key: (hello world)\n") == 0); + xfree (buf); + nvc_release (pk); + } + else + { + err = nvc_set_private_key (pk, key); + assert (gpg_err_code (err) == GPG_ERR_MISSING_KEY); + } } @@ -403,7 +435,7 @@ convert (const char *fname) exit (1); } - pk = nvc_new (); + pk = my_nvc_new (); assert (pk); err = nvc_set_private_key (pk, key); @@ -437,7 +469,10 @@ parse (const char *fname) exit (1); } - err = nvc_parse (&pk_a, &line, source); + if (private_key_mode) + err = nvc_parse_private_key (&pk_a, &line, source); + else + err = nvc_parse (&pk_a, &line, source); if (err) { fprintf (stderr, "failed to parse %s line %d: %s\n", @@ -448,14 +483,14 @@ parse (const char *fname) buf = nvc_to_string (pk_a); xfree (buf); - pk_b = nvc_new (); + pk_b = my_nvc_new (); assert (pk_b); for (e = nvc_first (pk_a); e; e = nve_next (e)) { gcry_sexp_t key = NULL; - if (strcasecmp (nve_name (e), "Key:") == 0) + if (private_key_mode && !strcasecmp (nve_name (e), "Key:")) { err = nvc_get_private_key (pk_a, &key); if (err) @@ -487,7 +522,8 @@ print_usage (void) fprintf (stderr, "usage: t-private-keys [--verbose]" " [--convert " - " || --parse ]\n"); + " || --parse-key " + " || --parse ]\n"); exit (2); } @@ -495,7 +531,7 @@ print_usage (void) int main (int argc, char **argv) { - enum { TEST, CONVERT, PARSE } command = TEST; + enum { TEST, CONVERT, PARSE, PARSEKEY } command = TEST; if (argc) { argc--; argv++; } @@ -513,6 +549,14 @@ main (int argc, char **argv) print_usage (); } + if (argc && !strcmp (argv[0], "--parse-key")) + { + command = PARSEKEY; + argc--; argv++; + if (argc != 1) + print_usage (); + } + if (argc && !strcmp (argv[0], "--parse")) { command = PARSE; @@ -524,6 +568,9 @@ main (int argc, char **argv) switch (command) { case TEST: + run_tests (); + run_modification_tests (); + private_key_mode = 1; run_tests (); run_modification_tests (); break; @@ -532,6 +579,11 @@ main (int argc, char **argv) convert (*argv); break; + case PARSEKEY: + private_key_mode = 1; + parse (*argv); + break; + case PARSE: parse (*argv); break; -- cgit From c14ef10fc347d966a1efcb5c2000cbf3aaafa905 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 28 Jun 2016 17:59:17 +0200 Subject: common: Fix memory leaks. * common/ccparray.c (ccparray_put): Free old array. * common/stringhelp.c (do_make_filename): Free 'home'. * common/t-convert.c: Fix trivial memory leaks. * common/t-iobuf.c: Likewise. * common/t-mbox-util.c: Likewise. * common/t-name-value.c: Likewise. * common/t-stringhelp.c: Likewise. * common/t-strlist.c: Likewise. Signed-off-by: Justus Winter --- common/ccparray.c | 1 + common/stringhelp.c | 2 ++ common/t-convert.c | 2 ++ common/t-iobuf.c | 15 ++++++++++++++- common/t-mbox-util.c | 2 ++ common/t-name-value.c | 4 ++-- common/t-stringhelp.c | 7 +++++++ common/t-strlist.c | 2 ++ 8 files changed, 32 insertions(+), 3 deletions(-) (limited to 'common/t-name-value.c') diff --git a/common/ccparray.c b/common/ccparray.c index 490dbf5c0..d3c28333c 100644 --- a/common/ccparray.c +++ b/common/ccparray.c @@ -114,6 +114,7 @@ ccparray_put (ccparray_t *cpa, const char *value) } for (n=0; n < cpa->size; n++) newarray[n] = cpa->array[n]; + xfree (cpa->array); cpa->array = newarray; cpa->size = newsize; diff --git a/common/stringhelp.c b/common/stringhelp.c index 0e96c9e54..95912e0b2 100644 --- a/common/stringhelp.c +++ b/common/stringhelp.c @@ -538,6 +538,7 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr) home_buffer = xtrymalloc (n); if (!home_buffer) { + xfree (home); xfree (name); return NULL; } @@ -556,6 +557,7 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr) else strcpy (stpcpy (stpcpy (p, home), "/"), name); + xfree (home); xfree (name); name = home_buffer; /* Let's do a simple compression to catch the most common diff --git a/common/t-convert.c b/common/t-convert.c index ad33dff9b..68824e0cd 100644 --- a/common/t-convert.c +++ b/common/t-convert.c @@ -234,6 +234,7 @@ test_bin2hex (void) fail (0); else if (strcmp (p, hexstuff)) fail (0); + xfree (p); p = bin2hex (stuff, (size_t)(-1), NULL); if (p) @@ -266,6 +267,7 @@ test_bin2hexcolon (void) fail (0); else if (strcmp (p, hexstuff)) fail (0); + xfree (p); p = bin2hexcolon (stuff, (size_t)(-1), NULL); if (p) diff --git a/common/t-iobuf.c b/common/t-iobuf.c index 2835df4d2..0e6f508a5 100644 --- a/common/t-iobuf.c +++ b/common/t-iobuf.c @@ -190,6 +190,8 @@ main (int argc, char *argv[]) n ++; } assert (n == 10 + (strlen (content) - 10) / 2); + + iobuf_close (iobuf); } @@ -266,6 +268,8 @@ main (int argc, char *argv[]) /* The string should have been truncated (max_len == 0). */ assert (max_len == 0); free (buffer); + + iobuf_close (iobuf); } { @@ -279,10 +283,12 @@ main (int argc, char *argv[]) int c; int n; int lastc = 0; + struct content_filter_state *state; iobuf = iobuf_temp_with_content (content, strlen(content)); rc = iobuf_push_filter (iobuf, - content_filter, content_filter_new (content2)); + content_filter, + state=content_filter_new (content2)); assert (rc == 0); n = 0; @@ -309,6 +315,9 @@ main (int argc, char *argv[]) /* printf ("%d: '%c' (%d)\n", n, c, c); */ } } + + iobuf_close (iobuf); + free (state); } /* Write some data to a temporary filter. Push a new filter. The @@ -346,6 +355,8 @@ main (int argc, char *argv[]) assert (n == strlen (content) + 2 * (strlen (content2) + 1)); assert (strcmp (buffer, "0123456789aabbcc") == 0); + + iobuf_close (iobuf); } { @@ -373,6 +384,8 @@ main (int argc, char *argv[]) assert (n == 2); assert (buffer[0] == '3'); assert (buffer[1] == '7'); + + iobuf_close (iobuf); } return 0; diff --git a/common/t-mbox-util.c b/common/t-mbox-util.c index dfa4ada2a..ff48f6c5d 100644 --- a/common/t-mbox-util.c +++ b/common/t-mbox-util.c @@ -87,6 +87,8 @@ run_test (void) fail (idx); else if (strcmp (mbox, testtbl[idx].mbox)) fail (idx); + + xfree (mbox); } } diff --git a/common/t-name-value.c b/common/t-name-value.c index fc9303bb8..3b01431d4 100644 --- a/common/t-name-value.c +++ b/common/t-name-value.c @@ -387,19 +387,19 @@ run_modification_tests (void) if (private_key_mode) { err = nvc_set_private_key (pk, key); - gcry_sexp_release (key); assert (err == 0); buf = nvc_to_string (pk); assert (strcmp (buf, "Key: (hello world)\n") == 0); xfree (buf); - nvc_release (pk); } else { err = nvc_set_private_key (pk, key); assert (gpg_err_code (err) == GPG_ERR_MISSING_KEY); } + gcry_sexp_release (key); + nvc_release (pk); } diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c index 4f4555e14..ccadf0222 100644 --- a/common/t-stringhelp.c +++ b/common/t-stringhelp.c @@ -223,6 +223,7 @@ test_strconcat (void) fail (0); else if (errno != EINVAL) fail (0); + xfree (out); #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ out = strconcat (NULL); @@ -232,6 +233,8 @@ test_strconcat (void) out = strconcat (NULL, NULL); if (!out || *out) fail (1); + xfree (out); + out = strconcat ("", NULL); if (!out || *out) fail (1); @@ -283,6 +286,7 @@ test_xstrconcat (void) "1", "2", "3", "4", "5", "6", "7", NULL); if (!out) fail (0); + xfree (out); #if __GNUC__ < 4 /* gcc 4.0 has a sentinel attribute. */ out = xstrconcat (NULL); @@ -292,6 +296,8 @@ test_xstrconcat (void) out = xstrconcat (NULL, NULL); if (!out) fail (1); + xfree (out); + out = xstrconcat ("", NULL); if (!out || *out) fail (1); @@ -534,6 +540,7 @@ test_strsplit (void) fail (tidx * 1000 + i + 1); } + xfree (fields); xfree (s2); } } diff --git a/common/t-strlist.c b/common/t-strlist.c index b03390593..e49d5a724 100644 --- a/common/t-strlist.c +++ b/common/t-strlist.c @@ -67,6 +67,8 @@ test_strlist_rev (void) fail (2); if (s->next->next->next) fail (2); + + free_strlist (s); } -- cgit