1 /* name-value.c - Parser and writer for a name-value format.
2 * Copyright (C) 2016 g10 Code GmbH
3 *
4 * This file is part of GnuPG.
5 *
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
8 *
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.
12 *
13 * or
14 *
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.
18 *
19 * or both in parallel, as here.
20 *
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.
25 *
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/>.
28 */
29
30 /*
31 * This module aso provides features for the extended private key
32 * format of gpg-agent.
33 */
34
35 #include <config.h>
36 #include <assert.h>
37 #include <gcrypt.h>
38 #include <gpg-error.h>
39 #include <string.h>
40
41 #include "mischelp.h"
42 #include "strlist.h"
43 #include "util.h"
44 #include "name-value.h"
45
46 struct name_value_container
47 {
48 struct name_value_entry *first;
49 struct name_value_entry *last;
50 unsigned int private_key_mode:1;
51 };
52
53
54 struct name_value_entry
55 {
56 struct name_value_entry *prev;
57 struct name_value_entry *next;
58
59 /* The name. Comments and blank lines have NAME set to NULL. */
60 char *name;
61
62 /* The value as stored in the file. We store it when we parse
63 a file so that we can reproduce it. */
64 strlist_t raw_value;
65
66 /* The decoded value. */
67 char *value;
68 };
69
70
71 /* Helper */
72 static inline gpg_error_t
my_error_from_syserror(void)73 my_error_from_syserror (void)
74 {
75 return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
76 }
77
78
79 static inline gpg_error_t
my_error(gpg_err_code_t ec)80 my_error (gpg_err_code_t ec)
81 {
82 return gpg_err_make (default_errsource, ec);
83 }
84
85
86
87
88 /* Allocation and deallocation. */
89
90 /* Allocate a private key container structure. */
91 nvc_t
nvc_new(void)92 nvc_new (void)
93 {
94 return xtrycalloc (1, sizeof (struct name_value_container));
95 }
96
97
98 /* Allocate a private key container structure for use with private keys. */
99 nvc_t
nvc_new_private_key(void)100 nvc_new_private_key (void)
101 {
102 nvc_t nvc = nvc_new ();
103 if (nvc)
104 nvc->private_key_mode = 1;
105 return nvc;
106 }
107
108
109 static void
nve_release(nve_t entry,int private_key_mode)110 nve_release (nve_t entry, int private_key_mode)
111 {
112 if (entry == NULL)
113 return;
114
115 xfree (entry->name);
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);
121 else
122 free_strlist (entry->raw_value);
123 xfree (entry);
124 }
125
126
127 /* Release a private key container structure. */
128 void
nvc_release(nvc_t pk)129 nvc_release (nvc_t pk)
130 {
131 nve_t e, next;
132
133 if (pk == NULL)
134 return;
135
136 for (e = pk->first; e; e = next)
137 {
138 next = e->next;
139 nve_release (e, pk->private_key_mode);
140 }
141
142 xfree (pk);
143 }
144
145
146
147 /* Dealing with names and values. */
148
149 /* Check whether the given name is valid. Valid names start with a
150 letter, end with a colon, and contain only alphanumeric characters
151 and the hyphen. */
152 static int
valid_name(const char * name)153 valid_name (const char *name)
154 {
155 size_t i, len = strlen (name);
156
157 if (! alphap (name) || len == 0 || name[len - 1] != ':')
158 return 0;
159
160 for (i = 1; i < len - 1; i++)
161 if (! alnump (&name[i]) && name[i] != '-')
162 return 0;
163
164 return 1;
165 }
166
167
168 /* Makes sure that ENTRY has a RAW_VALUE. */
169 static gpg_error_t
assert_raw_value(nve_t entry)170 assert_raw_value (nve_t entry)
171 {
172 gpg_error_t err = 0;
173 size_t len, offset;
174 #define LINELEN 70
175 char buf[LINELEN+3];
176
177 if (entry->raw_value)
178 return 0;
179
180 len = strlen (entry->value);
181 offset = 0;
182 while (len)
183 {
184 size_t amount, linelen = LINELEN;
185
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);
189
190 /* See if the rest of the value fits in this line. */
191 if (len <= linelen)
192 amount = len;
193 else
194 {
195 size_t i;
196
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]))
200 break;
201
202 if (ascii_isspace (entry->value[offset+i]))
203 {
204 /* Found one. */
205 amount = i;
206 }
207 else
208 {
209 /* Just induce a hard break. */
210 amount = linelen;
211 }
212 }
213
214 snprintf (buf, sizeof buf, " %.*s\n", (int) amount,
215 &entry->value[offset]);
216 if (append_to_strlist_try (&entry->raw_value, buf) == NULL)
217 {
218 err = my_error_from_syserror ();
219 goto leave;
220 }
221
222 offset += amount;
223 len -= amount;
224 }
225
226 leave:
227 if (err)
228 {
229 free_strlist_wipe (entry->raw_value);
230 entry->raw_value = NULL;
231 }
232
233 return err;
234 #undef LINELEN
235 }
236
237
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. */
242 static size_t
continuation_length(const char * s,int * swallow_ws,const char ** start)243 continuation_length (const char *s, int *swallow_ws, const char **start)
244 {
245 size_t len;
246
247 if (*swallow_ws)
248 {
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))
252 s++;
253 }
254 else
255 {
256 /* Iff a continuation starts with more than one space, it
257 encodes a space. */
258 if (ascii_isspace (*s))
259 s++;
260 }
261
262 /* Strip whitespace at the end. */
263 len = strlen (s);
264 while (len > 0 && ascii_isspace (s[len-1]))
265 len--;
266
267 if (len == 0)
268 {
269 /* Blank lines encode newlines. */
270 len = 1;
271 s = "\n";
272 *swallow_ws = 1;
273 }
274 else
275 *swallow_ws = 0;
276
277 if (start)
278 *start = s;
279
280 return len;
281 }
282
283
284 /* Makes sure that ENTRY has a VALUE. */
285 static gpg_error_t
assert_value(nve_t entry)286 assert_value (nve_t entry)
287 {
288 size_t len;
289 int swallow_ws;
290 strlist_t s;
291 char *p;
292
293 if (entry->value)
294 return 0;
295
296 len = 0;
297 swallow_ws = 0;
298 for (s = entry->raw_value; s; s = s->next)
299 len += continuation_length (s->d, &swallow_ws, NULL);
300
301 /* Add one for the terminating zero. */
302 len += 1;
303
304 entry->value = p = xtrymalloc (len);
305 if (entry->value == NULL)
306 return my_error_from_syserror ();
307
308 swallow_ws = 0;
309 for (s = entry->raw_value; s; s = s->next)
310 {
311 const char *start;
312 size_t l = continuation_length (s->d, &swallow_ws, &start);
313
314 memcpy (p, start, l);
315 p += l;
316 }
317
318 *p++ = 0;
319 assert (p - entry->value == len);
320
321 return 0;
322 }
323
324
325 /* Get the name. */
326 char *
nve_name(nve_t pke)327 nve_name (nve_t pke)
328 {
329 return pke->name;
330 }
331
332
333 /* Get the value. */
334 char *
nve_value(nve_t pke)335 nve_value (nve_t pke)
336 {
337 if (assert_value (pke))
338 return NULL;
339 return pke->value;
340 }
341
342
343
344 /* Adding and modifying values. */
345
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. */
350 static gpg_error_t
_nvc_add(nvc_t pk,char * name,char * value,strlist_t raw_value,int preserve_order)351 _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value,
352 int preserve_order)
353 {
354 gpg_error_t err = 0;
355 nve_t e;
356
357 assert (value || raw_value);
358
359 if (name && ! valid_name (name))
360 {
361 err = my_error (GPG_ERR_INV_NAME);
362 goto leave;
363 }
364
365 if (name
366 && pk->private_key_mode
367 && !ascii_strcasecmp (name, "Key:")
368 && nvc_lookup (pk, "Key:"))
369 {
370 err = my_error (GPG_ERR_INV_NAME);
371 goto leave;
372 }
373
374 e = xtrycalloc (1, sizeof *e);
375 if (e == NULL)
376 {
377 err = my_error_from_syserror ();
378 goto leave;
379 }
380
381 e->name = name;
382 e->value = value;
383 e->raw_value = raw_value;
384
385 if (pk->first)
386 {
387 nve_t last;
388
389 if (preserve_order || name == NULL)
390 last = pk->last;
391 else
392 {
393 /* See if there is already an entry with NAME. */
394 last = nvc_lookup (pk, name);
395
396 /* If so, find the last in that block. */
397 if (last)
398 {
399 while (last->next)
400 {
401 nve_t next = last->next;
402
403 if (next->name && ascii_strcasecmp (next->name, name) == 0)
404 last = next;
405 else
406 break;
407 }
408 }
409 else /* Otherwise, just find the last entry. */
410 last = pk->last;
411 }
412
413 if (last->next)
414 {
415 e->prev = last;
416 e->next = last->next;
417 last->next = e;
418 e->next->prev = e;
419 }
420 else
421 {
422 e->prev = last;
423 last->next = e;
424 pk->last = e;
425 }
426 }
427 else
428 pk->first = pk->last = e;
429
430 leave:
431 if (err)
432 {
433 xfree (name);
434 if (value)
435 wipememory (value, strlen (value));
436 xfree (value);
437 free_strlist_wipe (raw_value);
438 }
439
440 return err;
441 }
442
443
444 /* Add (NAME, VALUE) to PK. If an entry with NAME already exists, it
445 is not updated but the new entry is appended. */
446 gpg_error_t
nvc_add(nvc_t pk,const char * name,const char * value)447 nvc_add (nvc_t pk, const char *name, const char *value)
448 {
449 char *k, *v;
450
451 k = xtrystrdup (name);
452 if (k == NULL)
453 return my_error_from_syserror ();
454
455 v = xtrystrdup (value);
456 if (v == NULL)
457 {
458 xfree (k);
459 return my_error_from_syserror ();
460 }
461
462 return _nvc_add (pk, k, v, NULL, 0);
463 }
464
465
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. */
469 gpg_error_t
nvc_set(nvc_t pk,const char * name,const char * value)470 nvc_set (nvc_t pk, const char *name, const char *value)
471 {
472 nve_t e;
473
474 if (! valid_name (name))
475 return GPG_ERR_INV_NAME;
476
477 e = nvc_lookup (pk, name);
478 if (e)
479 {
480 char *v;
481
482 v = xtrystrdup (value);
483 if (v == NULL)
484 return my_error_from_syserror ();
485
486 free_strlist_wipe (e->raw_value);
487 e->raw_value = NULL;
488 if (e->value)
489 wipememory (e->value, strlen (e->value));
490 xfree (e->value);
491 e->value = v;
492
493 return 0;
494 }
495 else
496 return nvc_add (pk, name, value);
497 }
498
499
500 /* Delete the given entry from PK. */
501 void
nvc_delete(nvc_t pk,nve_t entry)502 nvc_delete (nvc_t pk, nve_t entry)
503 {
504 if (entry->prev)
505 entry->prev->next = entry->next;
506 else
507 pk->first = entry->next;
508
509 if (entry->next)
510 entry->next->prev = entry->prev;
511 else
512 pk->last = entry->prev;
513
514 nve_release (entry, pk->private_key_mode);
515 }
516
517
518 /* Delete the entries with NAME from PK. */
519 void
nvc_delete_named(nvc_t pk,const char * name)520 nvc_delete_named (nvc_t pk, const char *name)
521 {
522 nve_t e;
523
524 if (!valid_name (name))
525 return;
526
527 while ((e = nvc_lookup (pk, name)))
528 nvc_delete (pk, e);
529 }
530
531
532
533
534 /* Lookup and iteration. */
535
536 /* Get the first non-comment entry. */
537 nve_t
nvc_first(nvc_t pk)538 nvc_first (nvc_t pk)
539 {
540 nve_t entry;
541 for (entry = pk->first; entry; entry = entry->next)
542 if (entry->name)
543 return entry;
544 return NULL;
545 }
546
547
548 /* Get the first entry with the given name. */
549 nve_t
nvc_lookup(nvc_t pk,const char * name)550 nvc_lookup (nvc_t pk, const char *name)
551 {
552 nve_t entry;
553 for (entry = pk->first; entry; entry = entry->next)
554 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
555 return entry;
556 return NULL;
557 }
558
559
560 /* Get the next non-comment entry. */
561 nve_t
nve_next(nve_t entry)562 nve_next (nve_t entry)
563 {
564 for (entry = entry->next; entry; entry = entry->next)
565 if (entry->name)
566 return entry;
567 return NULL;
568 }
569
570
571 /* Get the next entry with the given name. */
572 nve_t
nve_next_value(nve_t entry,const char * name)573 nve_next_value (nve_t entry, const char *name)
574 {
575 for (entry = entry->next; entry; entry = entry->next)
576 if (entry->name && ascii_strcasecmp (entry->name, name) == 0)
577 return entry;
578 return NULL;
579 }
580
581
582 /* Return the string for the first entry in NVC with NAME. If an
583 * entry with NAME is missing in NVC or its value is the empty string
584 * NULL is returned. Note that the The returned string is a pointer
585 * into NVC. */
586 const char *
nvc_get_string(nvc_t nvc,const char * name)587 nvc_get_string (nvc_t nvc, const char *name)
588 {
589 nve_t item;
590
591 if (!nvc)
592 return NULL;
593 item = nvc_lookup (nvc, name);
594 if (!item)
595 return NULL;
596 return nve_value (item);
597 }
598
599
600
601
602 /* Private key handling. */
603
604 /* Get the private key. */
605 gpg_error_t
nvc_get_private_key(nvc_t pk,gcry_sexp_t * retsexp)606 nvc_get_private_key (nvc_t pk, gcry_sexp_t *retsexp)
607 {
608 gpg_error_t err;
609 nve_t e;
610
611 e = pk->private_key_mode? nvc_lookup (pk, "Key:") : NULL;
612 if (e == NULL)
613 return my_error (GPG_ERR_MISSING_KEY);
614
615 err = assert_value (e);
616 if (err)
617 return err;
618
619 return gcry_sexp_sscan (retsexp, NULL, e->value, strlen (e->value));
620 }
621
622
623 /* Set the private key. */
624 gpg_error_t
nvc_set_private_key(nvc_t pk,gcry_sexp_t sexp)625 nvc_set_private_key (nvc_t pk, gcry_sexp_t sexp)
626 {
627 gpg_error_t err;
628 char *raw, *clean, *p;
629 size_t len, i;
630
631 if (!pk->private_key_mode)
632 return my_error (GPG_ERR_MISSING_KEY);
633
634 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
635
636 raw = xtrymalloc (len);
637 if (raw == NULL)
638 return my_error_from_syserror ();
639
640 clean = xtrymalloc (len);
641 if (clean == NULL)
642 {
643 xfree (raw);
644 return my_error_from_syserror ();
645 }
646
647 gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, raw, len);
648
649 /* Strip any whitespace at the end. */
650 i = strlen (raw) - 1;
651 while (i && ascii_isspace (raw[i]))
652 {
653 raw[i] = 0;
654 i--;
655 }
656
657 /* Replace any newlines with spaces, remove superfluous whitespace. */
658 len = strlen (raw);
659 for (p = clean, i = 0; i < len; i++)
660 {
661 char c = raw[i];
662
663 /* Collapse contiguous and superfluous spaces. */
664 if (ascii_isspace (c) && i > 0
665 && (ascii_isspace (raw[i-1]) || raw[i-1] == '(' || raw[i-1] == ')'))
666 continue;
667
668 if (c == '\n')
669 c = ' ';
670
671 *p++ = c;
672 }
673 *p = 0;
674
675 err = nvc_set (pk, "Key:", clean);
676 xfree (raw);
677 xfree (clean);
678 return err;
679 }
680
681
682
683 /* Parsing and serialization. */
684
685 static gpg_error_t
do_nvc_parse(nvc_t * result,int * errlinep,estream_t stream,int for_private_key)686 do_nvc_parse (nvc_t *result, int *errlinep, estream_t stream,
687 int for_private_key)
688 {
689 gpg_error_t err = 0;
690 gpgrt_ssize_t len;
691 char *buf = NULL;
692 size_t buf_len = 0;
693 char *name = NULL;
694 strlist_t raw_value = NULL;
695
696 *result = for_private_key? nvc_new_private_key () : nvc_new ();
697 if (*result == NULL)
698 return my_error_from_syserror ();
699
700 if (errlinep)
701 *errlinep = 0;
702 while ((len = es_read_line (stream, &buf, &buf_len, NULL)) > 0)
703 {
704 char *p;
705 if (errlinep)
706 *errlinep += 1;
707
708 /* Skip any whitespace. */
709 for (p = buf; *p && ascii_isspace (*p); p++)
710 /* Do nothing. */;
711
712 if (name && (spacep (buf) || *p == 0))
713 {
714 /* A continuation. */
715 if (append_to_strlist_try (&raw_value, buf) == NULL)
716 {
717 err = my_error_from_syserror ();
718 goto leave;
719 }
720 continue;
721 }
722
723 /* No continuation. Add the current entry if any. */
724 if (raw_value)
725 {
726 err = _nvc_add (*result, name, NULL, raw_value, 1);
727 name = NULL;
728 if (err)
729 goto leave;
730 }
731
732 /* And prepare for the next one. */
733 name = NULL;
734 raw_value = NULL;
735
736 if (*p != 0 && *p != '#')
737 {
738 char *colon, *value, tmp;
739
740 colon = strchr (buf, ':');
741 if (colon == NULL)
742 {
743 err = my_error (GPG_ERR_INV_VALUE);
744 goto leave;
745 }
746
747 value = colon + 1;
748 tmp = *value;
749 *value = 0;
750 name = xtrystrdup (p);
751 *value = tmp;
752
753 if (name == NULL)
754 {
755 err = my_error_from_syserror ();
756 goto leave;
757 }
758
759 if (append_to_strlist_try (&raw_value, value) == NULL)
760 {
761 err = my_error_from_syserror ();
762 goto leave;
763 }
764 continue;
765 }
766
767 if (append_to_strlist_try (&raw_value, buf) == NULL)
768 {
769 err = my_error_from_syserror ();
770 goto leave;
771 }
772 }
773 if (len < 0)
774 {
775 err = gpg_error_from_syserror ();
776 goto leave;
777 }
778
779 /* Add the final entry. */
780 if (raw_value)
781 {
782 err = _nvc_add (*result, name, NULL, raw_value, 1);
783 name = NULL;
784 }
785
786 leave:
787 xfree (name);
788 gpgrt_free (buf);
789 if (err)
790 {
791 nvc_release (*result);
792 *result = NULL;
793 }
794
795 return err;
796 }
797
798
799 /* Parse STREAM and return a newly allocated name value container
800 structure in RESULT. If ERRLINEP is given, the line number the
801 parser was last considering is stored there. */
802 gpg_error_t
nvc_parse(nvc_t * result,int * errlinep,estream_t stream)803 nvc_parse (nvc_t *result, int *errlinep, estream_t stream)
804 {
805 return do_nvc_parse (result, errlinep, stream, 0);
806 }
807
808
809 /* Parse STREAM and return a newly allocated name value container
810 structure in RESULT - assuming the extended private key format. If
811 ERRLINEP is given, the line number the parser was last considering
812 is stored there. */
813 gpg_error_t
nvc_parse_private_key(nvc_t * result,int * errlinep,estream_t stream)814 nvc_parse_private_key (nvc_t *result, int *errlinep, estream_t stream)
815 {
816 return do_nvc_parse (result, errlinep, stream, 1);
817 }
818
819
820 /* Helper fpr nvc_write. */
821 static gpg_error_t
write_one_entry(nve_t entry,estream_t stream)822 write_one_entry (nve_t entry, estream_t stream)
823 {
824 gpg_error_t err;
825 strlist_t sl;
826
827 if (entry->name)
828 es_fputs (entry->name, stream);
829
830 err = assert_raw_value (entry);
831 if (err)
832 return err;
833
834 for (sl = entry->raw_value; sl; sl = sl->next)
835 es_fputs (sl->d, stream);
836
837 if (es_ferror (stream))
838 return my_error_from_syserror ();
839
840 return 0;
841 }
842
843
844 /* Write a representation of PK to STREAM. */
845 gpg_error_t
nvc_write(nvc_t pk,estream_t stream)846 nvc_write (nvc_t pk, estream_t stream)
847 {
848 gpg_error_t err = 0;
849 nve_t entry;
850 nve_t keyentry = NULL;
851
852 for (entry = pk->first; entry; entry = entry->next)
853 {
854 if (pk->private_key_mode
855 && entry->name && !ascii_strcasecmp (entry->name, "Key:"))
856 {
857 if (!keyentry)
858 keyentry = entry;
859 continue;
860 }
861
862 err = write_one_entry (entry, stream);
863 if (err)
864 return err;
865 }
866
867 /* In private key mode we write the Key always last. */
868 if (keyentry)
869 err = write_one_entry (keyentry, stream);
870
871 return err;
872 }
873