LCOV - code coverage report
Current view: top level - src - dn.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 333 667 49.9 %
Date: 2017-03-02 16:39:06 Functions: 19 23 82.6 %

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

Generated by: LCOV version 1.13