libksba  1.6.0
About: KSBA is a library to make the tasks of working with X.509 certificates, CMS data and related objects more easy.
  Fossies Dox: libksba-1.6.0.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

dn.c
Go to the documentation of this file.
1 /* dn.c - Distinguished Name helper functions
2  * Copyright (C) 2001, 2006, 2012 g10 Code GmbH
3  *
4  * This file is part of KSBA.
5  *
6  * KSBA 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  * KSBA is distributed in the hope that it will be useful, but WITHOUT
22  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24  * License for more details.
25  *
26  * You should have received a copies of the GNU General Public License
27  * and the GNU Lesser General Public License along with this program;
28  * if not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 /* Reference is RFC-2253 */
32 
33 #include <config.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <assert.h>
38 
39 #include "util.h"
40 #include "asn1-func.h"
41 #include "ber-help.h"
42 #include "ber-decoder.h"
43 #include "stringbuf.h"
44 
45 
46 static const struct {
47  const char *name;
48  int source; /* 0 = unknown
49  1 = rfc2253
50  2 = David Chadwick, July 2003
51  <draft-ietf-pkix-dnstrings-02.txt>
52  3 = Peter Gutmann
53  */
54  const char *description;
55  size_t oidlen;
56  const unsigned char *oid; /* DER encoded OID. */
57  const char *oidstr; /* OID as dotted string. */
58 } oid_name_tbl[] = {
59 {"CN", 1, "CommonName", 3, "\x55\x04\x03", "2.5.4.3" },
60 {"SN", 2, "Surname", 3, "\x55\x04\x04", "2.5.4.4" },
61 {"SERIALNUMBER", 2, "SerialNumber",3, "\x55\x04\x05", "2.5.4.5" },
62 {"C", 1, "CountryName", 3, "\x55\x04\x06", "2.5.4.6" },
63 {"L" , 1, "LocalityName", 3, "\x55\x04\x07", "2.5.4.7" },
64 {"ST", 1, "StateOrProvince", 3, "\x55\x04\x08", "2.5.4.8" },
65 {"STREET", 1, "StreetAddress", 3, "\x55\x04\x09", "2.5.4.9" },
66 {"O", 1, "OrganizationName", 3, "\x55\x04\x0a", "2.5.4.10" },
67 {"OU", 1, "OrganizationalUnit", 3, "\x55\x04\x0b", "2.5.4.11" },
68 {"T", 2, "Title", 3, "\x55\x04\x0c", "2.5.4.12" },
69 {"D", 3, "Description", 3, "\x55\x04\x0d", "2.5.4.13" },
70 {"BC", 3, "BusinessCategory", 3, "\x55\x04\x0f", "2.5.4.15" },
71 {"ADDR", 2, "PostalAddress", 3, "\x55\x04\x11", "2.5.4.16" },
72 {"POSTALCODE" , 0, "PostalCode", 3, "\x55\x04\x11", "2.5.4.17" },
73 {"GN", 2, "GivenName", 3, "\x55\x04\x2a", "2.5.4.42" },
74 {"PSEUDO", 2, "Pseudonym", 3, "\x55\x04\x41", "2.5.4.65" },
75 {"DC", 1, "domainComponent", 10,
76  "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19", "0.9.2342.19200300.100.1.25" },
77 {"UID", 1, "userid", 10,
78  "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01", "0.9.2342.19200300.100.1.1 " },
79 {"EMAIL", 3, "emailAddress", 9,
80  "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01", "1.2.840.113549.1.9.1" },
81 { NULL }
82 };
83 
84 
85 #define N 0x00
86 #define P 0x01
87 static unsigned char charclasses[128] = {
88  N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
89  N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
90  P, N, N, N, N, N, N, P, P, P, N, P, P, P, P, P,
91  P, P, P, P, P, P, P, P, P, P, P, N, N, P, N, P,
92  N, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
93  P, P, P, P, P, P, P, P, P, P, P, N, N, N, N, N,
94  N, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P,
95  P, P, P, P, P, P, P, P, P, P, P, N, N, N, N, N
96 };
97 #undef N
98 #undef P
99 
100 
101 /* This function is used for 1 byte encodings to insert any required
102  quoting. It does not do the quoting for a space or hash mark at
103  the beginning of a string or a space as the last character of a
104  string. It will do steps of SKIP+1 characters, assuming that these
105  SKIP characters are null octets. */
106 static void
107 append_quoted (struct stringbuf *sb, const unsigned char *value, size_t length,
108  int skip)
109 {
110  unsigned char tmp[4];
111  const unsigned char *s = value;
112  size_t n = 0;
113 
114  for (;;)
115  {
116  for (value = s; n+skip < length; n++, s++)
117  {
118  s += skip;
119  n += skip;
120  if (*s < ' ' || *s > 126 || strchr (",+\"\\<>;", *s) )
121  break;
122  }
123 
124  if (s != value)
125  put_stringbuf_mem_skip (sb, value, s-value, skip);
126  if (n+skip >= length)
127  return; /* ready */
128  s += skip;
129  n += skip;
130  if ( *s < ' ' || *s > 126 )
131  {
132  snprintf (tmp, sizeof tmp, "\\%02X", *s);
133  put_stringbuf_mem (sb, tmp, 3);
134  }
135  else
136  {
137  tmp[0] = '\\';
138  tmp[1] = *s;
139  put_stringbuf_mem (sb, tmp, 2);
140  }
141  n++; s++;
142  }
143 }
144 
145 ␌
146 /* Append VALUE of LENGTH and TYPE to SB. Do the required quoting. */
147 static void
148 append_utf8_value (const unsigned char *value, size_t length,
149  struct stringbuf *sb)
150 {
151  unsigned char tmp[6];
152  const unsigned char *s;
153  size_t n;
154  int i, nmore;
155 
156  if (length && (*value == ' ' || *value == '#'))
157  {
158  tmp[0] = '\\';
159  tmp[1] = *value;
160  put_stringbuf_mem (sb, tmp, 2);
161  value++;
162  length--;
163  }
164  if (length && value[length-1] == ' ')
165  {
166  tmp[0] = '\\';
167  tmp[1] = ' ';
168  put_stringbuf_mem (sb, tmp, 2);
169  length--;
170  }
171 
172  for (s=value, n=0;;)
173  {
174  for (value = s; n < length && !(*s & 0x80); n++, s++)
175  ;
176  if (s != value)
177  append_quoted (sb, value, s-value, 0);
178  if (n==length)
179  return; /* ready */
180  if (!(*s & 0x80))
181  nmore = 0; /* Not expected here: high bit not set. */
182  else if ( (*s & 0xe0) == 0xc0 ) /* 110x xxxx */
183  nmore = 1;
184  else if ( (*s & 0xf0) == 0xe0 ) /* 1110 xxxx */
185  nmore = 2;
186  else if ( (*s & 0xf8) == 0xf0 ) /* 1111 0xxx */
187  nmore = 3;
188  else if ( (*s & 0xfc) == 0xf8 ) /* 1111 10xx */
189  nmore = 4;
190  else if ( (*s & 0xfe) == 0xfc ) /* 1111 110x */
191  nmore = 5;
192  else /* Invalid encoding */
193  nmore = 0;
194 
195  if (!nmore)
196  {
197  /* Encoding error: We quote the bad byte. */
198  snprintf (tmp, sizeof tmp, "\\%02X", *s);
199  put_stringbuf_mem (sb, tmp, 3);
200  s++; n++;
201  }
202  else
203  {
204  tmp[0] = *s++; n++;
205  for (i=1; n < length && i <= nmore; i++)
206  {
207  if ( (*s & 0xc0) != 0x80)
208  break; /* Invalid encoding - let the next cycle detect this. */
209  tmp[i] = *s++;
210  n++;
211  }
212  put_stringbuf_mem (sb, tmp, i);
213  }
214  }
215 }
216 
217 /* Append VALUE of LENGTH and TYPE to SB. Do character set conversion
218  and quoting */
219 static void
220 append_latin1_value (const unsigned char *value, size_t length,
221  struct stringbuf *sb)
222 {
223  unsigned char tmp[2];
224  const unsigned char *s;
225  size_t n;
226 
227  if (length && (*value == ' ' || *value == '#'))
228  {
229  tmp[0] = '\\';
230  tmp[1] = *value;
231  put_stringbuf_mem (sb, tmp, 2);
232  value++;
233  length--;
234  }
235  if (length && value[length-1] == ' ')
236  {
237  tmp[0] = '\\';
238  tmp[1] = ' ';
239  put_stringbuf_mem (sb, tmp, 2);
240  length--;
241  }
242 
243  for (s=value, n=0;;)
244  {
245  for (value = s; n < length && !(*s & 0x80); n++, s++)
246  ;
247  if (s != value)
248  append_quoted (sb, value, s-value, 0);
249  if (n==length)
250  return; /* ready */
251  assert ((*s & 0x80));
252  tmp[0] = 0xc0 | ((*s >> 6) & 3);
253  tmp[1] = 0x80 | ( *s & 0x3f );
254  put_stringbuf_mem (sb, tmp, 2);
255  n++; s++;
256  }
257 }
258 
259 /* Append VALUE of LENGTH and TYPE to SB. Do UCS-4 to utf conversion
260  and and quoting */
261 static void
262 append_ucs4_value (const unsigned char *value, size_t length,
263  struct stringbuf *sb)
264 {
265  unsigned char tmp[7];
266  const unsigned char *s;
267  size_t n;
268  unsigned int c;
269  int i;
270 
271  if (length>3 && !value[0] && !value[1] && !value[2]
272  && (value[3] == ' ' || value[3] == '#'))
273  {
274  tmp[0] = '\\';
275  tmp[1] = *value;
276  put_stringbuf_mem (sb, tmp, 2);
277  value += 4;
278  length -= 4;
279  }
280  if (length>3 && !value[0] && !value[1] && !value[2] && value[3] == ' ')
281  {
282  tmp[0] = '\\';
283  tmp[1] = ' ';
284  put_stringbuf_mem (sb, tmp, 2);
285  length -= 4;
286  }
287 
288  for (s=value, n=0;;)
289  {
290  for (value = s; n+3 < length
291  && !s[0] && !s[1] && !s[2] && !(s[3] & 0x80); n += 4, s += 4)
292  ;
293  if (s != value)
294  append_quoted (sb, value, s-value, 3);
295  if (n>=length)
296  return; /* ready */
297  if (n < 4)
298  { /* This is an invalid encoding - better stop after adding
299  one impossible characater */
300  put_stringbuf_mem (sb, "\xff", 1);
301  return;
302  }
303  c = *s++ << 24;
304  c |= *s++ << 16;
305  c |= *s++ << 8;
306  c |= *s++;
307  n += 4;
308  i=0;
309  if (c < (1<<11))
310  {
311  tmp[i++] = 0xc0 | ( c >> 6);
312  tmp[i++] = 0x80 | ( c & 0x3f);
313  }
314  else if (c < (1<<16))
315  {
316  tmp[i++] = 0xe0 | ( c >> 12);
317  tmp[i++] = 0x80 | ((c >> 6) & 0x3f);
318  tmp[i++] = 0x80 | ( c & 0x3f);
319  }
320  else if (c < (1<<21))
321  {
322  tmp[i++] = 0xf0 | ( c >> 18);
323  tmp[i++] = 0x80 | ((c >> 12) & 0x3f);
324  tmp[i++] = 0x80 | ((c >> 6) & 0x3f);
325  tmp[i++] = 0x80 | ( c & 0x3f);
326  }
327  else if (c < (1<<26))
328  {
329  tmp[i++] = 0xf8 | ( c >> 24);
330  tmp[i++] = 0x80 | ((c >> 18) & 0x3f);
331  tmp[i++] = 0x80 | ((c >> 12) & 0x3f);
332  tmp[i++] = 0x80 | ((c >> 6) & 0x3f);
333  tmp[i++] = 0x80 | ( c & 0x3f);
334  }
335  else
336  {
337  tmp[i++] = 0xfc | ( c >> 30);
338  tmp[i++] = 0x80 | ((c >> 24) & 0x3f);
339  tmp[i++] = 0x80 | ((c >> 18) & 0x3f);
340  tmp[i++] = 0x80 | ((c >> 12) & 0x3f);
341  tmp[i++] = 0x80 | ((c >> 6) & 0x3f);
342  tmp[i++] = 0x80 | ( c & 0x3f);
343  }
344  put_stringbuf_mem (sb, tmp, i);
345  }
346 }
347 
348 /* Append VALUE of LENGTH and TYPE to SB. Do UCS-2 to utf conversion
349  and and quoting */
350 static void
351 append_ucs2_value (const unsigned char *value, size_t length,
352  struct stringbuf *sb)
353 {
354  unsigned char tmp[3];
355  const unsigned char *s;
356  size_t n;
357  unsigned int c;
358  int i;
359 
360  if (length>1 && !value[0] && (value[1] == ' ' || value[1] == '#'))
361  {
362  tmp[0] = '\\';
363  tmp[1] = *value;
364  put_stringbuf_mem (sb, tmp, 2);
365  value += 2;
366  length -= 2;
367  }
368  if (length>1 && !value[0] && value[1] == ' ')
369  {
370  tmp[0] = '\\';
371  tmp[1] = ' ';
372  put_stringbuf_mem (sb, tmp, 2);
373  length -=2;
374  }
375 
376  for (s=value, n=0;;)
377  {
378  for (value = s; n+1 < length && !s[0] && !(s[1] & 0x80); n += 2, s += 2)
379  ;
380  if (s != value)
381  append_quoted (sb, value, s-value, 1);
382  if (n>=length)
383  return; /* ready */
384  if (n < 2)
385  { /* This is an invalid encoding - better stop after adding
386  one impossible characater */
387  put_stringbuf_mem (sb, "\xff", 1);
388  return;
389  }
390  c = *s++ << 8;
391  c |= *s++;
392  n += 2;
393  i=0;
394  if (c < (1<<11))
395  {
396  tmp[i++] = 0xc0 | ( c >> 6);
397  tmp[i++] = 0x80 | ( c & 0x3f);
398  }
399  else
400  {
401  tmp[i++] = 0xe0 | ( c >> 12);
402  tmp[i++] = 0x80 | ((c >> 6) & 0x3f);
403  tmp[i++] = 0x80 | ( c & 0x3f);
404  }
405  put_stringbuf_mem (sb, tmp, i);
406  }
407 }
408 
409 
410 /* Append attribute and value. ROOT is the sequence */
411 static gpg_error_t
412 append_atv (const unsigned char *image, AsnNode root, struct stringbuf *sb)
413 {
414  AsnNode node = root->down;
415  const char *name;
416  int use_hex = 0;
417  int i;
418 
419  if (!node || node->type != TYPE_OBJECT_ID)
420  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
421  if (node->off == -1)
422  return gpg_error (GPG_ERR_NO_VALUE); /* Hmmm, this might lead to misunderstandings */
423 
424  name = NULL;
425  for (i=0; oid_name_tbl[i].name; i++)
426  {
427  if (oid_name_tbl[i].source == 1
428  && node->len == oid_name_tbl[i].oidlen
429  && !memcmp (image+node->off+node->nhdr,
430  oid_name_tbl[i].oid, node->len))
431  {
432  name = oid_name_tbl[i].name;
433  break;
434  }
435  }
436  if (name)
437  put_stringbuf (sb, name);
438  else
439  { /* No name for the OID in the table; at least not DER encoded.
440  Now convert the OID to a string, try to find it in the table
441  again and use the string as last resort. */
442  char *p;
443 
444  p = ksba_oid_to_str (image+node->off+node->nhdr, node->len);
445  if (!p)
446  return gpg_error (GPG_ERR_ENOMEM);
447 
448  for (i=0; *p && oid_name_tbl[i].name; i++)
449  {
450  if (oid_name_tbl[i].source == 1
451  && !strcmp (p, oid_name_tbl[i].oidstr))
452  {
453  name = oid_name_tbl[i].name;
454  break;
455  }
456  }
457  if (name)
458  put_stringbuf (sb, name);
459  else
460  {
461  put_stringbuf (sb, p);
462  use_hex = 1;
463  }
464  xfree (p);
465  }
466  put_stringbuf (sb, "=");
467  node = node->right;
468  if (!node || node->off == -1)
469  return gpg_error (GPG_ERR_NO_VALUE);
470 
471  switch (use_hex? 0 : node->type)
472  {
473  case TYPE_UTF8_STRING:
474  append_utf8_value (image+node->off+node->nhdr, node->len, sb);
475  break;
477  case TYPE_IA5_STRING:
478  /* we assume that wrong encodings are latin-1 */
479  case TYPE_TELETEX_STRING: /* Not correct, but mostly used as latin-1 */
480  append_latin1_value (image+node->off+node->nhdr, node->len, sb);
481  break;
482 
484  append_ucs4_value (image+node->off+node->nhdr, node->len, sb);
485  break;
486 
487  case TYPE_BMP_STRING:
488  append_ucs2_value (image+node->off+node->nhdr, node->len, sb);
489  break;
490 
491  case 0: /* forced usage of hex */
492  default:
493  put_stringbuf (sb, "#");
494  for (i=0; i < node->len; i++)
495  {
496  char tmp[3];
497  snprintf (tmp, sizeof tmp, "%02X", image[node->off+node->nhdr+i]);
498  put_stringbuf (sb, tmp);
499  }
500  break;
501  }
502 
503  return 0;
504 }
505 
506 static gpg_error_t
507 dn_to_str (const unsigned char *image, AsnNode root, struct stringbuf *sb)
508 {
509  gpg_error_t err;
510  AsnNode nset;
511 
512  if (!root )
513  return 0; /* empty DN */
514  nset = root->down;
515  if (!nset)
516  return 0; /* consider this as empty */
517  if (nset->type != TYPE_SET_OF)
518  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
519 
520  /* output in reverse order */
521  while (nset->right)
522  nset = nset->right;
523 
524  for (;;)
525  {
526  AsnNode nseq;
527 
528  if (nset->type != TYPE_SET_OF)
529  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
530  for (nseq = nset->down; nseq; nseq = nseq->right)
531  {
532  if (nseq->type != TYPE_SEQUENCE)
533  return gpg_error (GPG_ERR_UNEXPECTED_TAG);
534  if (nseq != nset->down)
535  put_stringbuf (sb, "+");
536  err = append_atv (image, nseq, sb);
537  if (err)
538  return err;
539  }
540  if (nset == root->down)
541  break;
542  put_stringbuf (sb, ",");
543  nset = nset->left;
544  }
545 
546  return 0;
547 }
548 
549 
550 gpg_error_t
551 _ksba_dn_to_str (const unsigned char *image, AsnNode node, char **r_string)
552 {
553  gpg_error_t err;
554  struct stringbuf sb;
555 
556  *r_string = NULL;
557  if (!node || node->type != TYPE_SEQUENCE_OF)
558  return gpg_error (GPG_ERR_INV_VALUE);
559 
560  init_stringbuf (&sb, 100);
561  err = dn_to_str (image, node, &sb);
562  if (!err)
563  {
564  *r_string = get_stringbuf (&sb);
565  if (!*r_string)
566  err = gpg_error (GPG_ERR_ENOMEM);
567  }
568  deinit_stringbuf (&sb);
569 
570  return err;
571 }
572 
573 ␌
574 /* Create a new decoder and run it for the given element */
575 /* Fixme: this code is duplicated from cms-parser.c */
576 static gpg_error_t
577 create_and_run_decoder (ksba_reader_t reader, const char *elem_name,
578  AsnNode *r_root,
579  unsigned char **r_image, size_t *r_imagelen)
580 {
581  gpg_error_t err;
582  ksba_asn_tree_t crl_tree;
583  BerDecoder decoder;
584 
585  err = ksba_asn_create_tree ("tmttv2", &crl_tree);
586  if (err)
587  return err;
588 
589  decoder = _ksba_ber_decoder_new ();
590  if (!decoder)
591  {
592  ksba_asn_tree_release (crl_tree);
593  return gpg_error (GPG_ERR_ENOMEM);
594  }
595 
596  err = _ksba_ber_decoder_set_reader (decoder, reader);
597  if (err)
598  {
599  ksba_asn_tree_release (crl_tree);
600  _ksba_ber_decoder_release (decoder);
601  return err;
602  }
603 
604  err = _ksba_ber_decoder_set_module (decoder, crl_tree);
605  if (err)
606  {
607  ksba_asn_tree_release (crl_tree);
608  _ksba_ber_decoder_release (decoder);
609  return err;
610  }
611 
612  err = _ksba_ber_decoder_decode (decoder, elem_name, 0,
613  r_root, r_image, r_imagelen);
614 
615  _ksba_ber_decoder_release (decoder);
616  ksba_asn_tree_release (crl_tree);
617  return err;
618 }
619 
620 
621 gpg_error_t
622 _ksba_derdn_to_str (const unsigned char *der, size_t derlen, char **r_string)
623 {
624  gpg_error_t err;
625  AsnNode root;
626  unsigned char *image;
627  size_t imagelen;
628  ksba_reader_t reader;
629 
630  err = ksba_reader_new (&reader);
631  if (err)
632  return err;
633  err = ksba_reader_set_mem (reader, der, derlen);
634  if (err)
635  {
636  ksba_reader_release (reader);
637  return err;
638  }
639  err = create_and_run_decoder (reader,
640  "TMTTv2.CertificateList.tbsCertList.issuer",
641  &root, &image, &imagelen);
642  ksba_reader_release (reader);
643  if (!err)
644  {
645  err = _ksba_dn_to_str (image, root->down, r_string);
647  xfree (image);
648  }
649  return err;
650 }
651 
652 ␌
653 /*
654  Convert a string back to DN
655 */
656 
657 /* Count the number of bytes in a quoted string, return a pointer to
658  the character after the string or NULL in case of an paring error.
659  The number of bytes needed to store the string verbatim will be
660  return as RESULT. With V2COMAP true, the string is assumed to be
661  in v2 quoting (but w/o the leading quote character)
662  */
663 static const char *
664 count_quoted_string (const char *string, size_t *result,
665  int v2compat, int *stringtype)
666 {
667  const unsigned char *s;
668  int nbytes = 0;
669  int highbit = 0;
670  int nonprint = 0;
671  int atsign = 0;
672 
673  *stringtype = 0;
674  for (s=string; *s; s++)
675  {
676  if (*s == '\\')
677  { /* pair */
678  s++;
679  if (*s == ',' || *s == '=' || *s == '+'
680  || *s == '<' || *s == '>' || *s == '#' || *s == ';'
681  || *s == '\\' || *s == '\"' || *s == ' ')
682  {
683  if (!charclasses[*s])
684  nonprint = 1;
685  nbytes++;
686  }
687  else if (hexdigitp (s) && hexdigitp (s+1))
688  {
689  int c = xtoi_2 (s);
690  if ((c & 0x80))
691  highbit = 1;
692  else if (c == '@')
693  atsign = 1;
694  else if (!charclasses[c])
695  nonprint = 1;
696 
697  s++;
698  nbytes++;
699  }
700  else
701  return NULL; /* invalid escape sequence */
702  }
703  else if (*s == '\"')
704  {
705  if (v2compat)
706  break;
707  return NULL; /* invalid encoding */
708  }
709  else if (!v2compat
710  && (*s == ',' || *s == '=' || *s == '+'
711  || *s == '<' || *s == '>' || *s == '#' || *s == ';') )
712  {
713  break;
714  }
715  else
716  {
717  nbytes++;
718  if ((*s & 0x80))
719  highbit = 1;
720  else if (*s == '@')
721  atsign = 1;
722  else if (!charclasses[*s])
723  nonprint = 1;
724  }
725  }
726 
727  /* Fixme: Should be remove spaces or white spces from the end unless
728  they are not escaped or we are in v2compat mode? See TODO */
729 
730  if (highbit || nonprint)
731  *stringtype = TYPE_UTF8_STRING;
732  else if (atsign)
733  *stringtype = TYPE_IA5_STRING;
734  else
735  *stringtype = TYPE_PRINTABLE_STRING;
736 
737  *result = nbytes;
738  return s;
739 }
740 
741 
742 /* Write out the data to W and do the required escaping. Note that
743  NBYTES is the number of bytes actually to be written, i.e. it is
744  the result from count_quoted_string */
745 static gpg_error_t
746 write_escaped (ksba_writer_t w, const unsigned char *buffer, size_t nbytes)
747 {
748  const unsigned char *s;
749  gpg_error_t err;
750 
751  for (s=buffer; nbytes; s++)
752  {
753  if (*s == '\\')
754  {
755  s++;
756  if (hexdigitp (s) && hexdigitp (s+1))
757  {
758  unsigned char buf = xtoi_2 (s);
759  err = ksba_writer_write (w, &buf, 1);
760  if (err)
761  return err;
762  s++;
763  nbytes--;
764  }
765  else
766  {
767  err = ksba_writer_write (w, s, 1);
768  if (err)
769  return err;
770  nbytes--;
771  }
772  }
773  else
774  {
775  err = ksba_writer_write (w, s, 1);
776  if (err)
777  return err;
778  nbytes--;
779  }
780  }
781 
782  return 0;
783 }
784 
785 
786 /* Parse one RDN, and write it to WRITER. Returns a pointer to the
787  next RDN part where the comma has already been skipped or NULL in
788  case of an error. When NULL is passed as WRITER, the function does
789  not allocate any memory but just parses the string and returns the
790  ENDP. If ROFF or RLEN are not NULL, they will receive informaion
791  useful for error reporting. */
792 static gpg_error_t
793 parse_rdn (const unsigned char *string, const char **endp,
794  ksba_writer_t writer, size_t *roff, size_t *rlen)
795 {
796  const unsigned char *orig_string = string;
797  const unsigned char *s, *s1;
798  size_t n, n1;
799  int i;
800  unsigned char *p;
801  unsigned char *oidbuf = NULL;
802  unsigned char *valuebuf = NULL;
803  const unsigned char *oid = NULL;
804  size_t oidlen;
805  const unsigned char *value = NULL;
806  int valuelen;
807  int valuetype;
808  int need_escaping = 0;
809  gpg_error_t err = 0;
810  size_t dummy_roff, dummy_rlen;
811 
812  if (!roff)
813  roff = &dummy_roff;
814  if (!rlen)
815  rlen = &dummy_rlen;
816 
817  *roff = *rlen = 0;
818 
819  if (!string)
820  return gpg_error (GPG_ERR_INV_VALUE);
821  while (*string == ' ')
822  string++;
823  *roff = string - orig_string;
824  if (!*string)
825  return gpg_error (GPG_ERR_SYNTAX); /* empty elements are not allowed */
826  s = string;
827 
828  if ( ((*s == 'o' && s[1] == 'i' && s[2] == 'd')
829  ||(*s == 'O' && s[1] == 'I' && s[2] == 'D'))
830  && s[3] == '.' && digitp (s+4))
831  s += 3; /* skip a prefixed oid */
832 
833  /* parse attributeType */
834  string = s;
835  *roff = string - orig_string;
836  if (digitp (s))
837  { /* oid */
838  for (s++; digitp (s) || (*s == '.' && s[1] != '.'); s++)
839  ;
840  n = s - string;
841  while (*s == ' ')
842  s++;
843  if (*s != '=')
844  return gpg_error (GPG_ERR_SYNTAX);
845 
846  if (writer)
847  {
848  p = xtrymalloc (n+1);
849  if (!p)
850  return gpg_error (GPG_ERR_ENOMEM);
851  memcpy (p, string, n);
852  p[n] = 0;
853  err = ksba_oid_from_str (p, &oidbuf, &oidlen);
854  xfree (p);
855  if (err)
856  return err;
857  oid = oidbuf;
858  }
859  }
860  else if ((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') )
861  { /* name */
862  for (s++; ((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')
863  || digitp (s) || *s == '-'); s++)
864  ;
865  n = s - string;
866  while (*s == ' ')
867  s++;
868  if (*s != '=')
869  return gpg_error (GPG_ERR_SYNTAX);
870 
871  for (i=0; oid_name_tbl[i].name; i++)
872  {
873  if ( n == strlen (oid_name_tbl[i].name)
874  && !ascii_memcasecmp (string, oid_name_tbl[i].name, n))
875  break;
876  }
877  if (!oid_name_tbl[i].name)
878  {
879  *roff = string - orig_string;
880  *rlen = n;
881  return gpg_error (GPG_ERR_UNKNOWN_NAME);
882  }
883  oid = oid_name_tbl[i].oid;
884  oidlen = oid_name_tbl[i].oidlen;
885  }
886  else
887  return gpg_error (GPG_ERR_INV_NAME);
888 
889  s++;
890  while (*s == ' ')
891  s++;
892  string = s;
893 
894  *roff = string - orig_string;
895 
896  /* parse attributeValue */
897  if (!*s)
898  {
899  err = gpg_error (GPG_ERR_SYNTAX); /* missing value */
900  goto leave;
901  }
902 
903  if (*s == '#')
904  { /* hexstring */
905  int need_utf8 = 0;
906  int need_ia5 = 0;
907 
908  string = ++s;
909  for (; hexdigitp (s); s++)
910  s++;
911  n = s - string;
912  if (!n || (n & 1))
913  {
914  *rlen = n;
915  err = gpg_error (GPG_ERR_SYNTAX); /* no hex digits or odd number */
916  goto leave;
917  }
918  while (*s == ' ')
919  s++;
920  n /= 2;
921  valuelen = n;
922  if (writer)
923  {
924  valuebuf = xtrymalloc (valuelen);
925  if (!valuebuf)
926  {
927  err = gpg_error (GPG_ERR_ENOMEM);
928  goto leave;
929  }
930  for (p=valuebuf, s1=string; n; p++, s1 += 2, n--)
931  {
932  *p = xtoi_2 (s1);
933  if (*p == '@')
934  need_ia5 = 1;
935  else if ((*p & 0x80) || !charclasses[*p])
936  need_utf8 = 1;
937  }
938  value = valuebuf;
939  }
940  else
941  {
942  for (s1=string; n; s1 += 2, n--)
943  {
944  unsigned int c;
945 
946  c = xtoi_2 (s1);
947  if (c == '@')
948  need_ia5 = 1;
949  else if ((c & 0x80) || !charclasses[c])
950  need_utf8 = 1;
951  }
952  }
953  valuetype = need_utf8? TYPE_UTF8_STRING :
955  }
956  else if (*s == '\"')
957  { /* old style quotation */
958  string = s+1;
959  s = count_quoted_string (string, &n, 1, &valuetype);
960  if (!s || *s != '\"')
961  {
962  *rlen = s - orig_string;
963  err = gpg_error (GPG_ERR_SYNTAX); /* error or quote not closed */
964  goto leave;
965  }
966  s++;
967  while (*s == ' ')
968  s++;
969  value = string;
970  valuelen = n;
971  need_escaping = 1;
972  }
973  else
974  { /* regular v3 quoted string */
975  s = count_quoted_string (string, &n, 0, &valuetype);
976  if (!s)
977  {
978  err = gpg_error (GPG_ERR_SYNTAX); /* error */
979  goto leave;
980  }
981  while (*s == ' ')
982  s++;
983  value = string;
984  valuelen = n;
985  need_escaping = 1;
986  }
987 
988  if (!valuelen)
989  {
990  err = gpg_error (GPG_ERR_SYNTAX); /* empty elements are not allowed */
991  goto leave;
992  }
993  if ( *s && *s != ',' && *s != ';' && *s != '+')
994  {
995  *roff = s - orig_string;
996  err = gpg_error (GPG_ERR_SYNTAX); /* invalid delimiter */
997  goto leave;
998  }
999  if (*s == '+') /* fixme: implement this */
1000  {
1001  *roff = s - orig_string;
1002  *rlen = 1;
1003  err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1004  goto leave;
1005  }
1006  *endp = *s? (s+1):s;
1007 
1008  if (writer)
1009  { /* write out the data */
1010 
1011  /* need to calculate the length in advance */
1013  n1 += oidlen;
1014  n1 += _ksba_ber_count_tl (valuetype, CLASS_UNIVERSAL, 0, valuelen);
1015  n1 += valuelen;
1016 
1017  /* The SET tag */
1019  n += n1;
1020  err = _ksba_ber_write_tl (writer, TYPE_SET, CLASS_UNIVERSAL, 1, n);
1021 
1022  /* The sequence tag */
1023  n = n1;
1024  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1025 
1026  /* the OBJECT ID */
1028  0, oidlen);
1029  if (!err)
1030  err = ksba_writer_write (writer, oid, oidlen);
1031  if (err)
1032  goto leave;
1033 
1034  /* the value. Note that we don't need any conversion to the target
1035  characters set because the input is expected to be utf8 and the
1036  target type is either utf8, IA5 or printable string where the last
1037  two are subsets of utf8 */
1038  err = _ksba_ber_write_tl (writer, valuetype,
1039  CLASS_UNIVERSAL, 0, valuelen);
1040  if (!err)
1041  err = need_escaping? write_escaped (writer, value, valuelen)
1042  : ksba_writer_write (writer, value, valuelen);
1043  }
1044 
1045  leave:
1046  xfree (oidbuf);
1047  xfree (valuebuf);
1048  return err;
1049 }
1050 
1051 
1052 
1053 gpg_error_t
1054 _ksba_dn_from_str (const char *string, char **rbuf, size_t *rlength)
1055 {
1056  gpg_error_t err;
1057  ksba_writer_t writer;
1058  const char *s, *endp;
1059  void *buf = NULL;
1060  size_t buflen;
1061  char const **part_array = NULL;
1062  int part_array_size, nparts;
1063 
1064  *rbuf = NULL; *rlength = 0;
1065  /* We are going to build the object using a writer object. */
1066  err = ksba_writer_new (&writer);
1067  if (!err)
1068  err = ksba_writer_set_mem (writer, 1024);
1069  if (err)
1070  return err;
1071 
1072  /* We must assign it in reverse order so we do it in 2 passes. */
1073  part_array_size = 0;
1074  for (nparts=0, s=string; s && *s;)
1075  {
1076  err = parse_rdn (s, &endp, NULL, NULL, NULL);
1077  if (err)
1078  goto leave;
1079  if (nparts >= part_array_size)
1080  {
1081  char const **tmp;
1082 
1083  part_array_size += 2;
1084  tmp = part_array_size? xtryrealloc (part_array,
1085  part_array_size * sizeof *tmp)
1086  : xtrymalloc (part_array_size * sizeof *tmp);
1087  if (!tmp)
1088  {
1089  err = gpg_error (GPG_ERR_ENOMEM);
1090  goto leave;
1091  }
1092  part_array = tmp;
1093  }
1094  part_array[nparts++] = s;
1095  s = endp;
1096  }
1097  if (!nparts)
1098  {
1099  err = gpg_error (GPG_ERR_SYNTAX);
1100  goto leave;
1101  }
1102 
1103  while (--nparts >= 0)
1104  {
1105  err = parse_rdn (part_array[nparts], &endp, writer, NULL, NULL);
1106  if (err)
1107  goto leave;
1108  }
1109 
1110  /* Now get the memory. */
1111  buf = ksba_writer_snatch_mem (writer, &buflen);
1112  if (!buf)
1113  {
1114  err = gpg_error (GPG_ERR_ENOMEM);
1115  goto leave;
1116  }
1117  /* Reinitialize the buffer to create the outer sequence. */
1118  err = ksba_writer_set_mem (writer, buflen + 10);
1119  if (err)
1120  goto leave;
1121 
1122  /* write the outer sequence */
1123  err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE,
1124  CLASS_UNIVERSAL, 1, buflen);
1125  if (err)
1126  goto leave;
1127  /* write the collected sets */
1128  err = ksba_writer_write (writer, buf, buflen);
1129  if (err)
1130  goto leave;
1131 
1132  /* and get the result */
1133  *rbuf = ksba_writer_snatch_mem (writer, rlength);
1134  if (!*rbuf)
1135  {
1136  err = gpg_error (GPG_ERR_ENOMEM);
1137  goto leave;
1138  }
1139 
1140  leave:
1141  xfree (part_array);
1142  ksba_writer_release (writer);
1143  xfree (buf);
1144  return err;
1145 }
1146 
1147 
1148 
1149 gpg_error_t
1150 ksba_dn_der2str (const void *der, size_t derlen, char **rstring)
1151 {
1152  return _ksba_derdn_to_str (der, derlen, rstring);
1153 }
1154 
1155 
1156 gpg_error_t
1157 ksba_dn_str2der (const char *string, unsigned char **rder, size_t *rderlen)
1158 {
1159  return _ksba_dn_from_str (string, (char**)rder, rderlen);
1160 }
1161 
1162 
1163 
1164 /* Assuming that STRING contains an rfc2253 encoded string, test
1165  whether this string may be passed as a valid DN to libksba. On
1166  success the functions returns 0. On error the function returns an
1167  error code and stores the offset within STRING of the erroneous
1168  part at RERROFF. RERRLEN will then receive the length of the
1169  erroneous part. This function is most useful to test whether a
1170  symbolic name (like SN) is supported. SEQ should be passed as 0 for
1171  now. RERROFF and RERRLEN may be passed as NULL if the caller is
1172  not interested at this value. */
1173 gpg_error_t
1174 ksba_dn_teststr (const char *string, int seq,
1175  size_t *rerroff, size_t *rerrlen)
1176 {
1177  size_t dummy_erroff, dummy_errlen;
1178  gpg_error_t err;
1179  int nparts;
1180  const char *s, *endp;
1181  size_t off, len;
1182 
1183  if (!rerroff)
1184  rerroff = &dummy_erroff;
1185  if (!rerrlen)
1186  rerrlen = &dummy_errlen;
1187 
1188  *rerrlen = *rerroff = 0;
1189 
1190  for (nparts=0, s=string; s && *s; nparts++)
1191  {
1192  err = parse_rdn (s, &endp, NULL, &off, &len);
1193  if (err && !seq--)
1194  {
1195  *rerroff = s - string + off;
1196  *rerrlen = len? len : strlen (s);
1197  return err;
1198  }
1199  s = endp;
1200  }
1201  if (!nparts)
1202  return gpg_error (GPG_ERR_SYNTAX);
1203  return 0;
1204 }
@ TYPE_SEQUENCE_OF
@ TYPE_TELETEX_STRING
@ TYPE_UNIVERSAL_STRING
@ TYPE_OBJECT_ID
@ TYPE_BMP_STRING
@ TYPE_SET_OF
@ TYPE_IA5_STRING
@ TYPE_PRINTABLE_STRING
@ TYPE_SEQUENCE
@ TYPE_SET
@ TYPE_UTF8_STRING
@ CLASS_UNIVERSAL
void _ksba_asn_release_nodes(AsnNode node)
Definition: asn1-parse.c:2886
gpg_error_t _ksba_ber_decoder_decode(BerDecoder d, const char *start_name, unsigned int flags, AsnNode *r_root, unsigned char **r_image, size_t *r_imagelen)
Definition: ber-decoder.c:1203
gpg_error_t _ksba_ber_decoder_set_module(BerDecoder d, ksba_asn_tree_t module)
Definition: ber-decoder.c:373
BerDecoder _ksba_ber_decoder_new(void)
Definition: ber-decoder.c:344
void _ksba_ber_decoder_release(BerDecoder d)
Definition: ber-decoder.c:356
gpg_error_t _ksba_ber_decoder_set_reader(BerDecoder d, ksba_reader_t r)
Definition: ber-decoder.c:386
gpg_error_t _ksba_ber_write_tl(ksba_writer_t writer, unsigned long tag, enum tag_class class, int constructed, unsigned long length)
Definition: ber-help.c:316
size_t _ksba_ber_count_tl(unsigned long tag, enum tag_class class, int constructed, unsigned long length)
Definition: ber-help.c:434
#define N
Definition: dn.c:85
int source
Definition: dn.c:48
const unsigned char * oid
Definition: dn.c:56
gpg_error_t _ksba_dn_from_str(const char *string, char **rbuf, size_t *rlength)
Definition: dn.c:1054
static const char * count_quoted_string(const char *string, size_t *result, int v2compat, int *stringtype)
Definition: dn.c:664
static gpg_error_t write_escaped(ksba_writer_t w, const unsigned char *buffer, size_t nbytes)
Definition: dn.c:746
size_t oidlen
Definition: dn.c:55
#define P
Definition: dn.c:86
const char * oidstr
Definition: dn.c:57
gpg_error_t _ksba_dn_to_str(const unsigned char *image, AsnNode node, char **r_string)
Definition: dn.c:551
static gpg_error_t parse_rdn(const unsigned char *string, const char **endp, ksba_writer_t writer, size_t *roff, size_t *rlen)
Definition: dn.c:793
const char * description
Definition: dn.c:54
const char * name
Definition: dn.c:47
gpg_error_t _ksba_derdn_to_str(const unsigned char *der, size_t derlen, char **r_string)
Definition: dn.c:622
static void append_latin1_value(const unsigned char *value, size_t length, struct stringbuf *sb)
Definition: dn.c:220
static gpg_error_t create_and_run_decoder(ksba_reader_t reader, const char *elem_name, AsnNode *r_root, unsigned char **r_image, size_t *r_imagelen)
Definition: dn.c:577
static const struct @26 oid_name_tbl[]
static void append_quoted(struct stringbuf *sb, const unsigned char *value, size_t length, int skip)
Definition: dn.c:107
static gpg_error_t append_atv(const unsigned char *image, AsnNode root, struct stringbuf *sb)
Definition: dn.c:412
static unsigned char charclasses[128]
Definition: dn.c:87
static void append_utf8_value(const unsigned char *value, size_t length, struct stringbuf *sb)
Definition: dn.c:148
static void append_ucs4_value(const unsigned char *value, size_t length, struct stringbuf *sb)
Definition: dn.c:262
static void append_ucs2_value(const unsigned char *value, size_t length, struct stringbuf *sb)
Definition: dn.c:351
static gpg_error_t dn_to_str(const unsigned char *image, AsnNode root, struct stringbuf *sb)
Definition: dn.c:507
#define GPG_ERR_SYNTAX
Definition: gen-help.h:81
#define GPG_ERR_INV_VALUE
Definition: gen-help.h:82
#define xtrymalloc(a)
Definition: gen-help.h:38
#define gpg_error(a)
Definition: gen-help.h:87
const unsigned char * der
Definition: keyinfo.c:367
unsigned int derlen
Definition: keyinfo.c:366
gpg_error_t ksba_writer_set_mem(ksba_writer_t w, size_t initial_size)
gpg_error_t ksba_writer_new(ksba_writer_t *r_w)
void ksba_reader_release(ksba_reader_t r)
gpg_error_t ksba_oid_from_str(const char *string, unsigned char **rbuf, size_t *rlength)
gpg_error_t ksba_writer_write(ksba_writer_t w, const void *buffer, size_t length)
gpg_error_t ksba_dn_der2str(const void *der, size_t derlen, char **r_string)
gpg_error_t ksba_reader_set_mem(ksba_reader_t r, const void *buffer, size_t length)
char * ksba_oid_to_str(const char *buffer, size_t length)
gpg_error_t ksba_dn_teststr(const char *string, int seq, size_t *rerroff, size_t *rerrlen)
void ksba_writer_release(ksba_writer_t w)
gpg_error_t ksba_asn_create_tree(const char *mod_name, ksba_asn_tree_t *result)
void * ksba_writer_snatch_mem(ksba_writer_t w, size_t *nbytes)
gpg_error_t ksba_dn_str2der(const char *string, unsigned char **rder, size_t *rderlen)
void ksba_asn_tree_release(ksba_asn_tree_t tree)
gpg_error_t ksba_reader_new(ksba_reader_t *r_r)
static void deinit_stringbuf(struct stringbuf *sb)
Definition: stringbuf.h:60
static void init_stringbuf(struct stringbuf *sb, int initiallen)
Definition: stringbuf.h:47
static char * get_stringbuf(struct stringbuf *sb)
Definition: stringbuf.h:164
static void put_stringbuf_mem_skip(struct stringbuf *sb, const char *text, size_t n, int skip)
Definition: stringbuf.h:93
static void put_stringbuf(struct stringbuf *sb, const char *text)
Definition: stringbuf.h:131
static void put_stringbuf_mem(struct stringbuf *sb, const char *text, size_t n)
Definition: stringbuf.h:69
AsnNode right
Definition: asn1-func.h:111
AsnNode down
Definition: asn1-func.h:110
node_type_t type
Definition: asn1-func.h:100
AsnNode left
Definition: asn1-func.h:112
size_t len
Definition: stringbuf.h:39
char * buf
Definition: stringbuf.h:41
#define xfree(a)
Definition: util.h:58
#define xtoi_2(p)
Definition: util.h:119
#define xtryrealloc(a, b)
Definition: util.h:56
#define digitp(p)
Definition: util.h:109
#define ascii_memcasecmp(a, b, n)
Definition: util.h:105
#define hexdigitp(a)
Definition: util.h:110