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);
482 v = xtrystrdup (value);
484 return my_error_from_syserror ();
486 free_strlist_wipe (e->raw_value);
489 wipememory (e->value, strlen (e->value));
496 return nvc_add (pk, name, value);
500 /* Update entry E to VALUE. */
502 nve_set (nve_t e, const char *value)
507 return GPG_ERR_INV_ARG;
509 v = xtrystrdup (value? value:"");
511 return my_error_from_syserror ();
513 free_strlist_wipe (e->raw_value);
516 wipememory (e->value, strlen (e->value));
524 /* Delete the given entry from PK. */
526 nvc_delete (nvc_t pk, nve_t entry)
529 entry->prev->next = entry->next;
531 pk->first = entry->next;
534 entry->next->prev = entry->prev;
536 pk->last = entry->prev;
538 nve_release (entry, pk->private_key_mode);
542 /* Delete the entries with NAME from PK. */
544 nvc_delete_named (nvc_t pk, const char *name)
548 if (!valid_name (name))
551 while ((e = nvc_lookup (pk, name)))
558 /* Lookup and iteration. */
560 /* Get the first non-comment entry. */
569 for (entry = pk->first; entry; entry = entry->next)
577 /* Get the first entry with the given name. Return NULL if it does
580 nvc_lookup (nvc_t pk, const char *name)
587 for (entry = pk->first; entry; entry = entry->next)
588 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
595 /* Get the next non-comment entry. */
597 nve_next (nve_t entry)
599 for (entry = entry->next; entry; entry = entry->next)
606 /* Get the next entry with the given name. */
608 nve_next_value (nve_t entry, const char *name)
610 for (entry = entry->next; entry; entry = entry->next)
611 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
617 /* Return the string for the first entry in NVC with NAME. If an
618 * entry with NAME is missing in NVC or its value is the empty string
619 * NULL is returned. Note that the the returned string is a pointer
622 nvc_get_string (nvc_t nvc, const char *name)
628 item = nvc_lookup (nvc, name);
631 return nve_value (item);
635 /* Return true (ie. a non-zero value) if NAME exists and its value is
636 * true; that is either "yes", "true", or a decimal value unequal to 0. */
638 nvc_get_boolean (nvc_t nvc, const char *name)
646 item = nvc_lookup (nvc, name);
649 s = nve_value (item);
655 if (!ascii_strcasecmp (s, "yes") || !ascii_strcasecmp (s, "true"))
663 /* Private key handling. */
665 /* Get the private key. */
667 nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp)
672 e = pk->private_key_mode? nvc_lookup (pk, "Key:") : NULL;
674 return my_error (GPG_ERR_MISSING_KEY);
676 err = assert_value (e);
680 return gcry_sexp_sscan (retsexp, NULL, e->value, strlen (e->value));
684 /* Set the private key. */
686 nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp)
689 char *raw, *clean, *p;
692 if (!pk->private_key_mode)
693 return my_error (GPG_ERR_MISSING_KEY);
695 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
697 raw = xtrymalloc (len);
699 return my_error_from_syserror ();
701 clean = xtrymalloc (len);
705 return my_error_from_syserror ();
708 gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, raw, len);
710 /* Strip any whitespace at the end. */
711 i = strlen (raw) - 1;
712 while (i && ascii_isspace (raw[i]))
718 /* Replace any newlines with spaces, remove superfluous whitespace. */
720 for (p = clean, i = 0; i < len; i++)
724 /* Collapse contiguous and superfluous spaces. */
725 if (ascii_isspace (c) && i > 0
726 && (ascii_isspace (raw[i-1]) || raw[i-1] == '(' || raw[i-1] == ')'))
736 err = nvc_set (pk, "Key:", clean);
744 /* Parsing and serialization. */
747 do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream,
755 strlist_t raw_value = NULL;
757 *result = for_private_key? nvc_new_private_key () : nvc_new ();
759 return my_error_from_syserror ();
763 while ((len = es_read_line (stream, &buf, &buf_len, NULL)) > 0)
769 /* Skip any whitespace. */
770 for (p = buf; *p && ascii_isspace (*p); p++)
773 if (name && (spacep (buf) || *p == 0))
775 /* A continuation. */
776 if (append_to_strlist_try (&raw_value, buf) == NULL)
778 err = my_error_from_syserror ();
784 /* No continuation. Add the current entry if any. */
787 err = _nvc_add (*result, name, NULL, raw_value, 1);
793 /* And prepare for the next one. */
797 if (*p != 0 && *p != '#')
799 char *colon, *value, tmp;
801 colon = strchr (buf, ':');
804 err = my_error (GPG_ERR_INV_VALUE);
811 name = xtrystrdup (p);
816 err = my_error_from_syserror ();
820 if (append_to_strlist_try (&raw_value, value) == NULL)
822 err = my_error_from_syserror ();
828 if (append_to_strlist_try (&raw_value, buf) == NULL)
830 err = my_error_from_syserror ();
836 err = gpg_error_from_syserror ();
840 /* Add the final entry. */
843 err = _nvc_add (*result, name, NULL, raw_value, 1);
852 nvc_release (*result);
860 /* Parse STREAM and return a newly allocated name value container
861 structure in RESULT. If ERRLINEP is given, the line number the
862 parser was last considering is stored there. */
864 nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
866 return do_nvc_parse (result, errlinep, stream, 0);
870 /* Parse STREAM and return a newly allocated name value container
871 structure in RESULT - assuming the extended private key format. If
872 ERRLINEP is given, the line number the parser was last considering
875 nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream)
877 return do_nvc_parse (result, errlinep, stream, 1);
881 /* Helper fpr nvc_write. */
883 write_one_entry (nve_t entry, estream_t stream)
889 es_fputs (entry->name, stream);
891 err = assert_raw_value (entry);
895 for (sl = entry->raw_value; sl; sl = sl->next)
896 es_fputs (sl->d, stream);
898 if (es_ferror (stream))
899 return my_error_from_syserror ();
905 /* Write a representation of PK to STREAM. */
907 nvc_write (nvc_t pk, estream_t stream)
911 nve_t keyentry = NULL;
913 for (entry = pk->first; entry; entry = entry->next)
915 if (pk->private_key_mode
916 && entry->name && !ascii_strcasecmp (entry->name, "Key:"))
923 err = write_one_entry (entry, stream);
928 /* In private key mode we write the Key always last. */
930 err = write_one_entry (keyentry, stream);