1 /* name-value.c - Parser and writer for a name-value format.
2 * Copyright (C) 2016 g10 Code GmbH
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * GnuPG is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses/>.
31 * This module aso provides features for the extended private key
32 * format of gpg-agent.
38 #include <gpg-error.h>
44 #include "name-value.h"
46 struct name_value_container
48 struct name_value_entry *first;
49 struct name_value_entry *last;
50 unsigned int private_key_mode:1;
54 struct name_value_entry
56 struct name_value_entry *prev;
57 struct name_value_entry *next;
59 /* The name. Comments and blank lines have NAME set to NULL. */
62 /* The value as stored in the file. We store it when we parse
63 a file so that we can reproduce it. */
66 /* The decoded value. */
72 static inline gpg_error_t
73 my_error_from_syserror (void)
75 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
79 static inline gpg_error_t
80 my_error (gpg_err_code_t ec)
82 return gpg_err_make (default_errsource, ec);
88 /* Allocation and deallocation. */
90 /* Allocate a private key container structure. */
94 return xtrycalloc (1, sizeof (struct name_value_container));
98 /* Allocate a private key container structure for use with private keys. */
100 nvc_new_private_key (void)
102 nvc_t nvc = nvc_new ();
104 nvc->private_key_mode = 1;
110 nve_release (nve_t entry, int private_key_mode)
116 if (entry->value && private_key_mode)
117 wipememory (entry->value, strlen (entry->value));
118 xfree (entry->value);
119 if (private_key_mode)
120 free_strlist_wipe (entry->raw_value);
122 free_strlist (entry->raw_value);
127 /* Release a private key container structure. */
129 nvc_release (nvc_t pk)
136 for (e = pk->first; e; e = next)
139 nve_release (e, pk->private_key_mode);
147 /* Dealing with names and values. */
149 /* Check whether the given name is valid. Valid names start with a
150 letter, end with a colon, and contain only alphanumeric characters
153 valid_name (const char *name)
155 size_t i, len = strlen (name);
157 if (! alphap (name) || len == 0 || name[len - 1] != ':')
160 for (i = 1; i < len - 1; i++)
161 if (! alnump (&name[i]) && name[i] != '-')
168 /* Makes sure that ENTRY has a RAW_VALUE. */
170 assert_raw_value (nve_t entry)
177 if (entry->raw_value)
180 len = strlen (entry->value);
184 size_t amount, linelen = LINELEN;
186 /* On the first line we need to subtract space for the name. */
187 if (entry->raw_value == NULL && strlen (entry->name) < linelen)
188 linelen -= strlen (entry->name);
190 /* See if the rest of the value fits in this line. */
197 /* Find a suitable space to break on. */
198 for (i = linelen - 1; linelen - i < 30; i--)
199 if (ascii_isspace (entry->value[offset+i]))
202 if (ascii_isspace (entry->value[offset+i]))
209 /* Just induce a hard break. */
214 snprintf (buf, sizeof buf, " %.*s\n", (int) amount,
215 &entry->value[offset]);
216 if (append_to_strlist_try (&entry->raw_value, buf) == NULL)
218 err = my_error_from_syserror ();
229 free_strlist_wipe (entry->raw_value);
230 entry->raw_value = NULL;
238 /* Computes the length of the value encoded as continuation. If
239 *SWALLOW_WS is set, all whitespace at the beginning of S is
240 swallowed. If START is given, a pointer to the beginning of the
241 value is stored there. */
243 continuation_length (const char *s, int *swallow_ws, const char **start)
249 /* The previous line was a blank line and we inserted a newline.
250 Swallow all whitespace at the beginning of this line. */
251 while (ascii_isspace (*s))
256 /* Iff a continuation starts with more than one space, it
258 if (ascii_isspace (*s))
262 /* Strip whitespace at the end. */
264 while (len > 0 && ascii_isspace (s[len-1]))
269 /* Blank lines encode newlines. */
284 /* Makes sure that ENTRY has a VALUE. */
286 assert_value (nve_t entry)
298 for (s = entry->raw_value; s; s = s->next)
299 len += continuation_length (s->d, &swallow_ws, NULL);
301 /* Add one for the terminating zero. */
304 entry->value = p = xtrymalloc (len);
305 if (entry->value == NULL)
306 return my_error_from_syserror ();
309 for (s = entry->raw_value; s; s = s->next)
312 size_t l = continuation_length (s->d, &swallow_ws, &start);
314 memcpy (p, start, l);
319 assert (p - entry->value == len);
335 nve_value (nve_t pke)
337 if (assert_value (pke))
344 /* Adding and modifying values. */
346 /* Add (NAME, VALUE, RAW_VALUE) to PK. NAME may be NULL for comments
347 and blank lines. At least one of VALUE and RAW_VALUE must be
348 given. If PRESERVE_ORDER is not given, entries with the same name
349 are grouped. NAME, VALUE and RAW_VALUE is consumed. */
351 _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value,
357 assert (value || raw_value);
359 if (name && ! valid_name (name))
361 err = my_error (GPG_ERR_INV_NAME);
366 && pk->private_key_mode
367 && !ascii_strcasecmp (name, "Key:")
368 && nvc_lookup (pk, "Key:"))
370 err = my_error (GPG_ERR_INV_NAME);
374 e = xtrycalloc (1, sizeof *e);
377 err = my_error_from_syserror ();
383 e->raw_value = raw_value;
389 if (preserve_order || name == NULL)
393 /* See if there is already an entry with NAME. */
394 last = nvc_lookup (pk, name);
396 /* If so, find the last in that block. */
401 nve_t next = last->next;
403 if (next->name && ascii_strcasecmp (next->name, name) == 0)
409 else /* Otherwise, just find the last entry. */
416 e->next = last->next;
428 pk->first = pk->last = e;
435 wipememory (value, strlen (value));
437 free_strlist_wipe (raw_value);
444 /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it
445 is not updated but the new entry is appended. */
447 nvc_add (nvc_t pk, const char *name, const char *value)
451 k = xtrystrdup (name);
453 return my_error_from_syserror ();
455 v = xtrystrdup (value);
459 return my_error_from_syserror ();
462 return _nvc_add (pk, k, v, NULL, 0);
466 /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it
467 is updated with VALUE. If multiple entries with NAME exist, the
468 first entry is updated. */
470 nvc_set (nvc_t pk, const char *name, const char *value)
474 if (! valid_name (name))
475 return GPG_ERR_INV_NAME;
477 e = nvc_lookup (pk, name);
479 return nve_set (e, value);
481 return nvc_add (pk, name, value);
485 /* Update entry E to VALUE. */
487 nve_set (nve_t e, const char *value)
492 return GPG_ERR_INV_ARG;
494 v = xtrystrdup (value? value:"");
496 return my_error_from_syserror ();
498 free_strlist_wipe (e->raw_value);
501 wipememory (e->value, strlen (e->value));
509 /* Delete the given entry from PK. */
511 nvc_delete (nvc_t pk, nve_t entry)
514 entry->prev->next = entry->next;
516 pk->first = entry->next;
519 entry->next->prev = entry->prev;
521 pk->last = entry->prev;
523 nve_release (entry, pk->private_key_mode);
526 /* Delete the entries with NAME from PK. */
528 nvc_delete_named (nvc_t pk, const char *name)
532 if (!valid_name (name))
535 while ((e = nvc_lookup (pk, name)))
542 /* Lookup and iteration. */
544 /* Get the first non-comment entry. */
549 for (entry = pk->first; entry; entry = entry->next)
556 /* Get the first entry with the given name. */
558 nvc_lookup (nvc_t pk, const char *name)
561 for (entry = pk->first; entry; entry = entry->next)
562 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
568 /* Get the next non-comment entry. */
570 nve_next (nve_t entry)
572 for (entry = entry->next; entry; entry = entry->next)
579 /* Get the next entry with the given name. */
581 nve_next_value (nve_t entry, const char *name)
583 for (entry = entry->next; entry; entry = entry->next)
584 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
590 /* Return the string for the first entry in NVC with NAME. If an
591 * entry with NAME is missing in NVC or its value is the empty string
592 * NULL is returned. Note that the returned string is a pointer
595 nvc_get_string (nvc_t nvc, const char *name)
601 item = nvc_lookup (nvc, name);
604 return nve_value (item);
608 /* Return true if NAME exists and its value is true; that is either
609 * "yes", "true", or a decimal value unequal to 0. */
611 nvc_get_boolean (nvc_t nvc, const char *name)
618 item = nvc_lookup (nvc, name);
621 s = nve_value (item);
623 || !ascii_strcasecmp (s, "yes")
624 || !ascii_strcasecmp (s, "true")))
631 /* Private key handling. */
633 /* Get the private key. */
635 nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp)
640 e = pk->private_key_mode? nvc_lookup (pk, "Key:") : NULL;
642 return my_error (GPG_ERR_MISSING_KEY);
644 err = assert_value (e);
648 return gcry_sexp_sscan (retsexp, NULL, e->value, strlen (e->value));
652 /* Set the private key. */
654 nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp)
657 char *raw, *clean, *p;
660 if (!pk->private_key_mode)
661 return my_error (GPG_ERR_MISSING_KEY);
663 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
665 raw = xtrymalloc (len);
667 return my_error_from_syserror ();
669 clean = xtrymalloc (len);
673 return my_error_from_syserror ();
676 gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, raw, len);
678 /* Strip any whitespace at the end. */
679 i = strlen (raw) - 1;
680 while (i && ascii_isspace (raw[i]))
686 /* Replace any newlines with spaces, remove superfluous whitespace. */
688 for (p = clean, i = 0; i < len; i++)
692 /* Collapse contiguous and superfluous spaces. */
693 if (ascii_isspace (c) && i > 0
694 && (ascii_isspace (raw[i-1]) || raw[i-1] == '(' || raw[i-1] == ')'))
704 err = nvc_set (pk, "Key:", clean);
712 /* Parsing and serialization. */
715 do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream,
723 strlist_t raw_value = NULL;
725 *result = for_private_key? nvc_new_private_key () : nvc_new ();
727 return my_error_from_syserror ();
731 while ((len = es_read_line (stream, &buf, &buf_len, NULL)) > 0)
737 /* Skip any whitespace. */
738 for (p = buf; *p && ascii_isspace (*p); p++)
741 if (name && (spacep (buf) || *p == 0))
743 /* A continuation. */
744 if (append_to_strlist_try (&raw_value, buf) == NULL)
746 err = my_error_from_syserror ();
752 /* No continuation. Add the current entry if any. */
755 err = _nvc_add (*result, name, NULL, raw_value, 1);
761 /* And prepare for the next one. */
765 if (*p != 0 && *p != '#')
767 char *colon, *value, tmp;
769 colon = strchr (buf, ':');
772 err = my_error (GPG_ERR_INV_VALUE);
779 name = xtrystrdup (p);
784 err = my_error_from_syserror ();
788 if (append_to_strlist_try (&raw_value, value) == NULL)
790 err = my_error_from_syserror ();
796 if (append_to_strlist_try (&raw_value, buf) == NULL)
798 err = my_error_from_syserror ();
804 err = gpg_error_from_syserror ();
808 /* Add the final entry. */
810 err = _nvc_add (*result, name, NULL, raw_value, 1);
816 nvc_release (*result);
824 /* Parse STREAM and return a newly allocated name value container
825 structure in RESULT. If ERRLINEP is given, the line number the
826 parser was last considering is stored there. */
828 nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
830 return do_nvc_parse (result, errlinep, stream, 0);
834 /* Parse STREAM and return a newly allocated name value container
835 structure in RESULT - assuming the extended private key format. If
836 ERRLINEP is given, the line number the parser was last considering
839 nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream)
841 return do_nvc_parse (result, errlinep, stream, 1);
845 /* Helper fpr nvc_write. */
847 write_one_entry (nve_t entry, estream_t stream)
853 es_fputs (entry->name, stream);
855 err = assert_raw_value (entry);
859 for (sl = entry->raw_value; sl; sl = sl->next)
860 es_fputs (sl->d, stream);
862 if (es_ferror (stream))
863 return my_error_from_syserror ();
869 /* Write a representation of PK to STREAM. */
871 nvc_write (nvc_t pk, estream_t stream)
875 nve_t keyentry = NULL;
877 for (entry = pk->first; entry; entry = entry->next)
879 if (pk->private_key_mode
880 && entry->name && !ascii_strcasecmp (entry->name, "Key:"))
887 err = write_one_entry (entry, stream);
892 /* In private key mode we write the Key always last. */
894 err = write_one_entry (keyentry, stream);