Coverage Report

Created: 2026-09-14 07:17

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