LCOV - code coverage report
Current view: top level - sm - certdump.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 399 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /* certdump.c - Dump a certificate for debugging
       2             :  * Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : #include <unistd.h>
      26             : #include <time.h>
      27             : #include <assert.h>
      28             : #ifdef HAVE_LOCALE_H
      29             : #include <locale.h>
      30             : #endif
      31             : #ifdef HAVE_LANGINFO_CODESET
      32             : #include <langinfo.h>
      33             : #endif
      34             : 
      35             : #include "gpgsm.h"
      36             : #include <gcrypt.h>
      37             : #include <ksba.h>
      38             : 
      39             : #include "keydb.h"
      40             : #include "i18n.h"
      41             : 
      42             : 
      43             : struct dn_array_s {
      44             :   char *key;
      45             :   char *value;
      46             :   int   multivalued;
      47             :   int   done;
      48             : };
      49             : 
      50             : 
      51             : /* Print the first element of an S-Expression. */
      52             : void
      53           0 : gpgsm_print_serial (estream_t fp, ksba_const_sexp_t sn)
      54             : {
      55           0 :   const char *p = (const char *)sn;
      56             :   unsigned long n;
      57             :   char *endp;
      58             : 
      59           0 :   if (!p)
      60           0 :     es_fputs (_("none"), fp);
      61           0 :   else if (*p != '(')
      62           0 :     es_fputs ("[Internal error - not an S-expression]", fp);
      63             :   else
      64             :     {
      65           0 :       p++;
      66           0 :       n = strtoul (p, &endp, 10);
      67           0 :       p = endp;
      68           0 :       if (*p++ != ':')
      69           0 :         es_fputs ("[Internal Error - invalid S-expression]", fp);
      70             :       else
      71           0 :         es_write_hexstring (fp, p, n, 0, NULL);
      72             :     }
      73           0 : }
      74             : 
      75             : 
      76             : /* Dump the serial number or any other simple S-expression. */
      77             : void
      78           0 : gpgsm_dump_serial (ksba_const_sexp_t sn)
      79             : {
      80           0 :   const char *p = (const char *)sn;
      81             :   unsigned long n;
      82             :   char *endp;
      83             : 
      84           0 :   if (!p)
      85           0 :     log_printf ("none");
      86           0 :   else if (*p != '(')
      87           0 :     log_printf ("ERROR - not an S-expression");
      88             :   else
      89             :     {
      90           0 :       p++;
      91           0 :       n = strtoul (p, &endp, 10);
      92           0 :       p = endp;
      93           0 :       if (*p!=':')
      94           0 :         log_printf ("ERROR - invalid S-expression");
      95             :       else
      96             :         {
      97           0 :           for (p++; n; n--, p++)
      98           0 :             log_printf ("%02X", *(const unsigned char *)p);
      99             :         }
     100             :     }
     101           0 : }
     102             : 
     103             : 
     104             : char *
     105           0 : gpgsm_format_serial (ksba_const_sexp_t sn)
     106             : {
     107           0 :   const char *p = (const char *)sn;
     108             :   unsigned long n;
     109             :   char *endp;
     110             :   char *buffer;
     111             :   int i;
     112             : 
     113           0 :   if (!p)
     114           0 :     return NULL;
     115             : 
     116           0 :   if (*p != '(')
     117           0 :     BUG (); /* Not a valid S-expression. */
     118             : 
     119           0 :   p++;
     120           0 :   n = strtoul (p, &endp, 10);
     121           0 :   p = endp;
     122           0 :   if (*p!=':')
     123           0 :     BUG (); /* Not a valid S-expression. */
     124           0 :   p++;
     125             : 
     126           0 :   buffer = xtrymalloc (n*2+1);
     127           0 :   if (buffer)
     128             :     {
     129           0 :       for (i=0; n; n--, p++, i+=2)
     130           0 :         sprintf (buffer+i, "%02X", *(unsigned char *)p);
     131           0 :       buffer[i] = 0;
     132             :     }
     133           0 :   return buffer;
     134             : }
     135             : 
     136             : 
     137             : 
     138             : 
     139             : void
     140           0 : gpgsm_print_time (estream_t fp, ksba_isotime_t t)
     141             : {
     142           0 :   if (!t || !*t)
     143           0 :     es_fputs (_("none"), fp);
     144             :   else
     145           0 :     es_fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s",
     146             :                 t, t+4, t+6, t+9, t+11, t+13);
     147           0 : }
     148             : 
     149             : 
     150             : void
     151           0 : gpgsm_dump_string (const char *string)
     152             : {
     153             : 
     154           0 :   if (!string)
     155           0 :     log_printf ("[error]");
     156             :   else
     157             :     {
     158             :       const unsigned char *s;
     159             : 
     160           0 :       for (s=(const unsigned char*)string; *s; s++)
     161             :         {
     162           0 :           if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
     163             :             break;
     164             :         }
     165           0 :       if (!*s && *string != '[')
     166           0 :         log_printf ("%s", string);
     167             :       else
     168             :         {
     169           0 :           log_printf ( "[ ");
     170           0 :           log_printhex (NULL, string, strlen (string));
     171           0 :           log_printf ( " ]");
     172             :         }
     173             :     }
     174           0 : }
     175             : 
     176             : 
     177             : /* This simple dump function is mainly used for debugging purposes. */
     178             : void
     179           0 : gpgsm_dump_cert (const char *text, ksba_cert_t cert)
     180             : {
     181             :   ksba_sexp_t sexp;
     182             :   char *p;
     183             :   char *dn;
     184             :   ksba_isotime_t t;
     185             : 
     186           0 :   log_debug ("BEGIN Certificate '%s':\n", text? text:"");
     187           0 :   if (cert)
     188             :     {
     189           0 :       sexp = ksba_cert_get_serial (cert);
     190           0 :       log_debug ("     serial: ");
     191           0 :       gpgsm_dump_serial (sexp);
     192           0 :       ksba_free (sexp);
     193           0 :       log_printf ("\n");
     194             : 
     195           0 :       ksba_cert_get_validity (cert, 0, t);
     196           0 :       log_debug ("  notBefore: ");
     197           0 :       dump_isotime (t);
     198           0 :       log_printf ("\n");
     199           0 :       ksba_cert_get_validity (cert, 1, t);
     200           0 :       log_debug ("   notAfter: ");
     201           0 :       dump_isotime (t);
     202           0 :       log_printf ("\n");
     203             : 
     204           0 :       dn = ksba_cert_get_issuer (cert, 0);
     205           0 :       log_debug ("     issuer: ");
     206           0 :       gpgsm_dump_string (dn);
     207           0 :       ksba_free (dn);
     208           0 :       log_printf ("\n");
     209             : 
     210           0 :       dn = ksba_cert_get_subject (cert, 0);
     211           0 :       log_debug ("    subject: ");
     212           0 :       gpgsm_dump_string (dn);
     213           0 :       ksba_free (dn);
     214           0 :       log_printf ("\n");
     215             : 
     216           0 :       log_debug ("  hash algo: %s\n", ksba_cert_get_digest_algo (cert));
     217             : 
     218           0 :       p = gpgsm_get_fingerprint_string (cert, 0);
     219           0 :       log_debug ("  SHA1 Fingerprint: %s\n", p);
     220           0 :       xfree (p);
     221             :     }
     222           0 :   log_debug ("END Certificate\n");
     223           0 : }
     224             : 
     225             : 
     226             : /* Return a new string holding the format serial number and issuer
     227             :    ("#SN/issuer").  No filtering on invalid characters is done.
     228             :    Caller must release the string.  On memory failure NULL is
     229             :    returned.  */
     230             : char *
     231           0 : gpgsm_format_sn_issuer (ksba_sexp_t sn, const char *issuer)
     232             : {
     233             :   char *p, *p1;
     234             : 
     235           0 :   if (sn && issuer)
     236             :     {
     237           0 :       p1 = gpgsm_format_serial (sn);
     238           0 :       if (!p1)
     239           0 :         p = xtrystrdup ("[invalid SN]");
     240             :       else
     241             :         {
     242           0 :           p = xtrymalloc (strlen (p1) + strlen (issuer) + 2 + 1);
     243           0 :           if (p)
     244             :             {
     245           0 :               *p = '#';
     246           0 :               strcpy (stpcpy (stpcpy (p+1, p1),"/"), issuer);
     247             :             }
     248           0 :           xfree (p1);
     249             :         }
     250             :     }
     251             :   else
     252           0 :     p = xtrystrdup ("[invalid SN/issuer]");
     253           0 :   return p;
     254             : }
     255             : 
     256             : 
     257             : /* Log the certificate's name in "#SN/ISSUERDN" format along with
     258             :    TEXT. */
     259             : void
     260           0 : gpgsm_cert_log_name (const char *text, ksba_cert_t cert)
     261             : {
     262           0 :   log_info ("%s", text? text:"certificate" );
     263           0 :   if (cert)
     264             :     {
     265             :       ksba_sexp_t sn;
     266             :       char *p;
     267             : 
     268           0 :       p = ksba_cert_get_issuer (cert, 0);
     269           0 :       sn = ksba_cert_get_serial (cert);
     270           0 :       if (p && sn)
     271             :         {
     272           0 :           log_printf (" #");
     273           0 :           gpgsm_dump_serial (sn);
     274           0 :           log_printf ("/");
     275           0 :           gpgsm_dump_string (p);
     276             :         }
     277             :       else
     278           0 :         log_printf (" [invalid]");
     279           0 :       ksba_free (sn);
     280           0 :       xfree (p);
     281             :     }
     282           0 :   log_printf ("\n");
     283           0 : }
     284             : 
     285             : 
     286             : 
     287             : 
     288             : 
     289             : 
     290             : /* helper for the rfc2253 string parser */
     291             : static const unsigned char *
     292           0 : parse_dn_part (struct dn_array_s *array, const unsigned char *string)
     293             : {
     294             :   static struct {
     295             :     const char *label;
     296             :     const char *oid;
     297             :   } label_map[] = {
     298             :     /* Warning: When adding new labels, make sure that the buffer
     299             :        below we be allocated large enough. */
     300             :     {"EMail",        "1.2.840.113549.1.9.1" },
     301             :     {"T",            "2.5.4.12" },
     302             :     {"GN",           "2.5.4.42" },
     303             :     {"SN",           "2.5.4.4" },
     304             :     {"NameDistinguisher", "0.2.262.1.10.7.20"},
     305             :     {"ADDR",         "2.5.4.16" },
     306             :     {"BC",           "2.5.4.15" },
     307             :     {"D",            "2.5.4.13" },
     308             :     {"PostalCode",   "2.5.4.17" },
     309             :     {"Pseudo",       "2.5.4.65" },
     310             :     {"SerialNumber", "2.5.4.5" },
     311             :     {NULL, NULL}
     312             :   };
     313             :   const unsigned char *s, *s1;
     314             :   size_t n;
     315             :   char *p;
     316             :   int i;
     317             : 
     318             :   /* Parse attributeType */
     319           0 :   for (s = string+1; *s && *s != '='; s++)
     320             :     ;
     321           0 :   if (!*s)
     322           0 :     return NULL; /* error */
     323           0 :   n = s - string;
     324           0 :   if (!n)
     325           0 :     return NULL; /* empty key */
     326             : 
     327             :   /* We need to allocate a few bytes more due to the possible mapping
     328             :      from the shorter OID to the longer label. */
     329           0 :   array->key = p = xtrymalloc (n+10);
     330           0 :   if (!array->key)
     331           0 :     return NULL;
     332           0 :   memcpy (p, string, n);
     333           0 :   p[n] = 0;
     334           0 :   trim_trailing_spaces (p);
     335             : 
     336           0 :   if (digitp (p))
     337             :     {
     338           0 :       for (i=0; label_map[i].label; i++ )
     339           0 :         if ( !strcmp (p, label_map[i].oid) )
     340             :           {
     341           0 :             strcpy (p, label_map[i].label);
     342           0 :             break;
     343             :           }
     344             :     }
     345           0 :   string = s + 1;
     346             : 
     347           0 :   if (*string == '#')
     348             :     { /* hexstring */
     349           0 :       string++;
     350           0 :       for (s=string; hexdigitp (s); s++)
     351           0 :         s++;
     352           0 :       n = s - string;
     353           0 :       if (!n || (n & 1))
     354           0 :         return NULL; /* Empty or odd number of digits. */
     355           0 :       n /= 2;
     356           0 :       array->value = p = xtrymalloc (n+1);
     357           0 :       if (!p)
     358           0 :         return NULL;
     359           0 :       for (s1=string; n; s1 += 2, n--, p++)
     360             :         {
     361           0 :           *(unsigned char *)p = xtoi_2 (s1);
     362           0 :           if (!*p)
     363           0 :             *p = 0x01; /* Better print a wrong value than truncating
     364             :                           the string. */
     365             :         }
     366           0 :       *p = 0;
     367             :    }
     368             :   else
     369             :     { /* regular v3 quoted string */
     370           0 :       for (n=0, s=string; *s; s++)
     371             :         {
     372           0 :           if (*s == '\\')
     373             :             { /* pair */
     374           0 :               s++;
     375           0 :               if (*s == ',' || *s == '=' || *s == '+'
     376           0 :                   || *s == '<' || *s == '>' || *s == '#' || *s == ';'
     377           0 :                   || *s == '\\' || *s == '\"' || *s == ' ')
     378           0 :                 n++;
     379           0 :               else if (hexdigitp (s) && hexdigitp (s+1))
     380             :                 {
     381           0 :                   s++;
     382           0 :                   n++;
     383             :                 }
     384             :               else
     385           0 :                 return NULL; /* invalid escape sequence */
     386             :             }
     387           0 :           else if (*s == '\"')
     388           0 :             return NULL; /* invalid encoding */
     389           0 :           else if (*s == ',' || *s == '=' || *s == '+'
     390           0 :                    || *s == '<' || *s == '>' || *s == ';' )
     391             :             break;
     392             :           else
     393           0 :             n++;
     394             :         }
     395             : 
     396           0 :       array->value = p = xtrymalloc (n+1);
     397           0 :       if (!p)
     398           0 :         return NULL;
     399           0 :       for (s=string; n; s++, n--)
     400             :         {
     401           0 :           if (*s == '\\')
     402             :             {
     403           0 :               s++;
     404           0 :               if (hexdigitp (s))
     405             :                 {
     406           0 :                   *(unsigned char *)p++ = xtoi_2 (s);
     407           0 :                   s++;
     408             :                 }
     409             :               else
     410           0 :                 *p++ = *s;
     411             :             }
     412             :           else
     413           0 :             *p++ = *s;
     414             :         }
     415           0 :       *p = 0;
     416             :     }
     417           0 :   return s;
     418             : }
     419             : 
     420             : 
     421             : /* Parse a DN and return an array-ized one.  This is not a validating
     422             :    parser and it does not support any old-stylish syntax; KSBA is
     423             :    expected to return only rfc2253 compatible strings. */
     424             : static struct dn_array_s *
     425           0 : parse_dn (const unsigned char *string)
     426             : {
     427             :   struct dn_array_s *array;
     428             :   size_t arrayidx, arraysize;
     429             :   int i;
     430             : 
     431           0 :   arraysize = 7; /* C,ST,L,O,OU,CN,email */
     432           0 :   arrayidx = 0;
     433           0 :   array = xtrymalloc ((arraysize+1) * sizeof *array);
     434           0 :   if (!array)
     435           0 :     return NULL;
     436           0 :   while (*string)
     437             :     {
     438           0 :       while (*string == ' ')
     439           0 :         string++;
     440           0 :       if (!*string)
     441           0 :         break; /* ready */
     442           0 :       if (arrayidx >= arraysize)
     443             :         {
     444             :           struct dn_array_s *a2;
     445             : 
     446           0 :           arraysize += 5;
     447           0 :           a2 = xtryrealloc (array, (arraysize+1) * sizeof *array);
     448           0 :           if (!a2)
     449           0 :             goto failure;
     450           0 :           array = a2;
     451             :         }
     452           0 :       array[arrayidx].key = NULL;
     453           0 :       array[arrayidx].value = NULL;
     454           0 :       string = parse_dn_part (array+arrayidx, string);
     455           0 :       if (!string)
     456           0 :         goto failure;
     457           0 :       while (*string == ' ')
     458           0 :         string++;
     459           0 :       array[arrayidx].multivalued = (*string == '+');
     460           0 :       array[arrayidx].done = 0;
     461           0 :       arrayidx++;
     462           0 :       if (*string && *string != ',' && *string != ';' && *string != '+')
     463           0 :         goto failure; /* invalid delimiter */
     464           0 :       if (*string)
     465           0 :         string++;
     466             :     }
     467           0 :   array[arrayidx].key = NULL;
     468           0 :   array[arrayidx].value = NULL;
     469           0 :   return array;
     470             : 
     471             :  failure:
     472           0 :   for (i=0; i < arrayidx; i++)
     473             :     {
     474           0 :       xfree (array[i].key);
     475           0 :       xfree (array[i].value);
     476             :     }
     477           0 :   xfree (array);
     478           0 :   return NULL;
     479             : }
     480             : 
     481             : 
     482             : /* Print a DN part to STREAM. */
     483             : static void
     484           0 : print_dn_part (estream_t stream,
     485             :                struct dn_array_s *dn, const char *key, int translate)
     486             : {
     487           0 :   struct dn_array_s *first_dn = dn;
     488             : 
     489           0 :   for (; dn->key; dn++)
     490             :     {
     491           0 :       if (!dn->done && !strcmp (dn->key, key))
     492             :         {
     493             :           /* Forward to the last multi-valued RDN, so that we can
     494             :              print them all in reverse in the correct order.  Note
     495             :              that this overrides the the standard sequence but that
     496             :              seems to a reasonable thing to do with multi-valued
     497             :              RDNs. */
     498           0 :           while (dn->multivalued && dn[1].key)
     499           0 :             dn++;
     500             :         next:
     501           0 :           if (!dn->done && dn->value && *dn->value)
     502             :             {
     503           0 :               es_fprintf (stream, "/%s=", dn->key);
     504           0 :               if (translate)
     505           0 :                 print_utf8_buffer3 (stream, dn->value, strlen (dn->value),
     506             :                                     "/");
     507             :               else
     508           0 :                 es_write_sanitized (stream, dn->value, strlen (dn->value),
     509             :                                     "/", NULL);
     510             :             }
     511           0 :           dn->done = 1;
     512           0 :           if (dn > first_dn && dn[-1].multivalued)
     513             :             {
     514           0 :               dn--;
     515           0 :               goto next;
     516             :             }
     517             :         }
     518             :     }
     519           0 : }
     520             : 
     521             : /* Print all parts of a DN in a "standard" sequence.  We first print
     522             :    all the known parts, followed by the uncommon ones */
     523             : static void
     524           0 : print_dn_parts (estream_t stream,
     525             :                 struct dn_array_s *dn, int translate)
     526             : {
     527           0 :   const char *stdpart[] = {
     528             :     "CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL
     529             :   };
     530             :   int i;
     531             : 
     532           0 :   for (i=0; stdpart[i]; i++)
     533           0 :       print_dn_part (stream, dn, stdpart[i], translate);
     534             : 
     535             :   /* Now print the rest without any specific ordering */
     536           0 :   for (; dn->key; dn++)
     537           0 :     print_dn_part (stream, dn, dn->key, translate);
     538           0 : }
     539             : 
     540             : 
     541             : /* Print the S-Expression in BUF to extended STREAM, which has a valid
     542             :    length of BUFLEN, as a human readable string in one line to FP. */
     543             : static void
     544           0 : pretty_es_print_sexp (estream_t fp, const unsigned char *buf, size_t buflen)
     545             : {
     546             :   size_t len;
     547             :   gcry_sexp_t sexp;
     548             :   char *result, *p;
     549             : 
     550           0 :   if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) )
     551             :     {
     552           0 :       es_fputs (_("[Error - invalid encoding]"), fp);
     553           0 :       return;
     554             :     }
     555           0 :   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
     556           0 :   assert (len);
     557           0 :   result = xtrymalloc (len);
     558           0 :   if (!result)
     559             :     {
     560           0 :       es_fputs (_("[Error - out of core]"), fp);
     561           0 :       gcry_sexp_release (sexp);
     562           0 :       return;
     563             :     }
     564           0 :   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
     565           0 :   assert (len);
     566           0 :   for (p = result; len; len--, p++)
     567             :     {
     568           0 :       if (*p == '\n')
     569             :         {
     570           0 :           if (len > 1) /* Avoid printing the trailing LF. */
     571           0 :             es_fputs ("\\n", fp);
     572             :         }
     573           0 :       else if (*p == '\r')
     574           0 :         es_fputs ("\\r", fp);
     575           0 :       else if (*p == '\v')
     576           0 :         es_fputs ("\\v", fp);
     577           0 :       else if (*p == '\t')
     578           0 :         es_fputs ("\\t", fp);
     579             :       else
     580           0 :         es_putc (*p, fp);
     581             :     }
     582           0 :   xfree (result);
     583           0 :   gcry_sexp_release (sexp);
     584             : }
     585             : 
     586             : 
     587             : /* This is a variant of gpgsm_print_name sending it output to an estream. */
     588             : void
     589           0 : gpgsm_es_print_name2 (estream_t fp, const char *name, int translate)
     590             : {
     591           0 :   const unsigned char *s = (const unsigned char *)name;
     592             :   int i;
     593             : 
     594           0 :   if (!s)
     595             :     {
     596           0 :       es_fputs (_("[Error - No name]"), fp);
     597             :     }
     598           0 :   else if (*s == '<')
     599             :     {
     600           0 :       const char *s2 = strchr ( (char*)s+1, '>');
     601             : 
     602           0 :       if (s2)
     603             :         {
     604           0 :           if (translate)
     605           0 :             print_utf8_buffer (fp, s + 1, s2 - (char*)s - 1);
     606             :           else
     607           0 :             es_write_sanitized (fp, s + 1, s2 - (char*)s - 1, NULL, NULL);
     608             :         }
     609             :     }
     610           0 :   else if (*s == '(')
     611             :     {
     612           0 :       pretty_es_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL));
     613             :     }
     614           0 :   else if (!((*s >= '0' && *s < '9')
     615           0 :              || (*s >= 'A' && *s <= 'Z')
     616           0 :              || (*s >= 'a' && *s <= 'z')))
     617           0 :     es_fputs (_("[Error - invalid encoding]"), fp);
     618             :   else
     619             :     {
     620           0 :       struct dn_array_s *dn = parse_dn (s);
     621             : 
     622           0 :       if (!dn)
     623           0 :         es_fputs (_("[Error - invalid DN]"), fp);
     624             :       else
     625             :         {
     626           0 :           print_dn_parts (fp, dn, translate);
     627           0 :           for (i=0; dn[i].key; i++)
     628             :             {
     629           0 :               xfree (dn[i].key);
     630           0 :               xfree (dn[i].value);
     631             :             }
     632           0 :           xfree (dn);
     633             :         }
     634             :     }
     635           0 : }
     636             : 
     637             : 
     638             : void
     639           0 : gpgsm_es_print_name (estream_t fp, const char *name)
     640             : {
     641           0 :   gpgsm_es_print_name2 (fp, name, 1);
     642           0 : }
     643             : 
     644             : 
     645             : /* A cookie structure used for the memory stream. */
     646             : struct format_name_cookie
     647             : {
     648             :   char *buffer;         /* Malloced buffer with the data to deliver. */
     649             :   size_t size;          /* Allocated size of this buffer. */
     650             :   size_t len;           /* strlen (buffer). */
     651             :   int error;            /* system error code if any. */
     652             : };
     653             : 
     654             : /* The writer function for the memory stream. */
     655             : static gpgrt_ssize_t
     656           0 : format_name_writer (void *cookie, const void *buffer, size_t size)
     657             : {
     658           0 :   struct format_name_cookie *c = cookie;
     659             :   char *p;
     660             : 
     661           0 :   if (!c->buffer)
     662             :     {
     663           0 :       p = xtrymalloc (size + 1 + 1);
     664           0 :       if (p)
     665             :         {
     666           0 :           c->size = size + 1;
     667           0 :           c->buffer = p;
     668           0 :           c->len = 0;
     669             :         }
     670             :     }
     671           0 :   else if (c->len + size < c->len)
     672             :     {
     673           0 :       p = NULL;
     674           0 :       gpg_err_set_errno (ENOMEM);
     675             :     }
     676           0 :   else if (c->size < c->len + size)
     677             :     {
     678           0 :       p = xtryrealloc (c->buffer, c->len + size + 1);
     679           0 :       if (p)
     680             :         {
     681           0 :           c->size = c->len + size;
     682           0 :           c->buffer = p;
     683             :         }
     684             :     }
     685             :   else
     686           0 :     p = c->buffer;
     687           0 :   if (!p)
     688             :     {
     689           0 :       c->error = errno;
     690           0 :       xfree (c->buffer);
     691           0 :       c->buffer = NULL;
     692           0 :       gpg_err_set_errno (c->error);
     693           0 :       return -1;
     694             :     }
     695           0 :   memcpy (p + c->len, buffer, size);
     696           0 :   c->len += size;
     697           0 :   p[c->len] = 0; /* Terminate string. */
     698             : 
     699           0 :   return (gpgrt_ssize_t)size;
     700             : }
     701             : 
     702             : 
     703             : /* Format NAME which is expected to be in rfc2253 format into a better
     704             :    human readable format. Caller must free the returned string.  NULL
     705             :    is returned in case of an error.  With TRANSLATE set to true the
     706             :    name will be translated to the native encoding.  Note that NAME is
     707             :    internally always UTF-8 encoded. */
     708             : char *
     709           0 : gpgsm_format_name2 (const char *name, int translate)
     710             : {
     711             :   estream_t fp;
     712             :   struct format_name_cookie cookie;
     713           0 :   es_cookie_io_functions_t io = { NULL };
     714             : 
     715           0 :   memset (&cookie, 0, sizeof cookie);
     716             : 
     717           0 :   io.func_write = format_name_writer;
     718           0 :   fp = es_fopencookie (&cookie, "w", io);
     719           0 :   if (!fp)
     720             :     {
     721           0 :       int save_errno = errno;
     722           0 :       log_error ("error creating memory stream: %s\n", strerror (save_errno));
     723           0 :       gpg_err_set_errno (save_errno);
     724           0 :       return NULL;
     725             :     }
     726           0 :   gpgsm_es_print_name2 (fp, name, translate);
     727           0 :   es_fclose (fp);
     728           0 :   if (cookie.error || !cookie.buffer)
     729             :     {
     730           0 :       xfree (cookie.buffer);
     731           0 :       gpg_err_set_errno (cookie.error);
     732           0 :       return NULL;
     733             :     }
     734           0 :   return cookie.buffer;
     735             : }
     736             : 
     737             : 
     738             : char *
     739           0 : gpgsm_format_name (const char *name)
     740             : {
     741           0 :   return gpgsm_format_name2 (name, 1);
     742             : }
     743             : 
     744             : 
     745             : /* Return fingerprint and a percent escaped name in a human readable
     746             :    format suitable for status messages like GOODSIG.  May return NULL
     747             :    on error (out of core). */
     748             : char *
     749           0 : gpgsm_fpr_and_name_for_status (ksba_cert_t cert)
     750             : {
     751             :   char *fpr, *name, *p;
     752             :   char *buffer;
     753             : 
     754           0 :   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
     755           0 :   if (!fpr)
     756           0 :     return NULL;
     757             : 
     758           0 :   name = ksba_cert_get_subject (cert, 0);
     759           0 :   if (!name)
     760             :     {
     761           0 :       xfree (fpr);
     762           0 :       return NULL;
     763             :     }
     764             : 
     765           0 :   p = gpgsm_format_name2 (name, 0);
     766           0 :   ksba_free (name);
     767           0 :   name = p;
     768           0 :   if (!name)
     769             :     {
     770           0 :       xfree (fpr);
     771           0 :       return NULL;
     772             :     }
     773             : 
     774           0 :   buffer = xtrymalloc (strlen (fpr) + 1 + 3*strlen (name) + 1);
     775           0 :   if (buffer)
     776             :     {
     777             :       const char *s;
     778             : 
     779           0 :       p = stpcpy (stpcpy (buffer, fpr), " ");
     780           0 :       for (s = name; *s; s++)
     781             :         {
     782           0 :           if (*s < ' ')
     783             :             {
     784           0 :               sprintf (p, "%%%02X", *(const unsigned char*)s);
     785           0 :               p += 3;
     786             :             }
     787             :           else
     788           0 :             *p++ = *s;
     789             :         }
     790           0 :       *p = 0;
     791             :     }
     792           0 :   xfree (fpr);
     793           0 :   xfree (name);
     794           0 :   return buffer;
     795             : }
     796             : 
     797             : 
     798             : /* Create a key description for the CERT, this may be passed to the
     799             :    pinentry.  The caller must free the returned string.  NULL may be
     800             :    returned on error. */
     801             : char *
     802           0 : gpgsm_format_keydesc (ksba_cert_t cert)
     803             : {
     804             :   char *name, *subject, *buffer;
     805             :   ksba_isotime_t t;
     806             :   char created[20];
     807             :   char expires[20];
     808             :   char *sn;
     809             :   ksba_sexp_t sexp;
     810             :   char *orig_codeset;
     811             : 
     812           0 :   name = ksba_cert_get_subject (cert, 0);
     813           0 :   subject = name? gpgsm_format_name2 (name, 0) : NULL;
     814           0 :   ksba_free (name); name = NULL;
     815             : 
     816           0 :   sexp = ksba_cert_get_serial (cert);
     817           0 :   sn = sexp? gpgsm_format_serial (sexp) : NULL;
     818           0 :   ksba_free (sexp);
     819             : 
     820           0 :   ksba_cert_get_validity (cert, 0, t);
     821           0 :   if (*t)
     822           0 :     sprintf (created, "%.4s-%.2s-%.2s", t, t+4, t+6);
     823             :   else
     824           0 :     *created = 0;
     825           0 :   ksba_cert_get_validity (cert, 1, t);
     826           0 :   if (*t)
     827           0 :     sprintf (expires, "%.4s-%.2s-%.2s", t, t+4, t+6);
     828             :   else
     829           0 :     *expires = 0;
     830             : 
     831           0 :   orig_codeset = i18n_switchto_utf8 ();
     832             : 
     833           0 :   name = xtryasprintf (_("Please enter the passphrase to unlock the"
     834             :                          " secret key for the X.509 certificate:\n"
     835             :                          "\"%s\"\n"
     836             :                          "S/N %s, ID 0x%08lX,\n"
     837             :                          "created %s, expires %s.\n" ),
     838             :                        subject? subject:"?",
     839             :                        sn? sn: "?",
     840             :                        gpgsm_get_short_fingerprint (cert, NULL),
     841             :                        created, expires);
     842             : 
     843           0 :   i18n_switchback (orig_codeset);
     844             : 
     845           0 :   if (!name)
     846             :     {
     847           0 :       xfree (subject);
     848           0 :       xfree (sn);
     849           0 :       return NULL;
     850             :     }
     851             : 
     852           0 :   xfree (subject);
     853           0 :   xfree (sn);
     854             : 
     855           0 :   buffer = percent_plus_escape (name);
     856           0 :   xfree (name);
     857           0 :   return buffer;
     858             : }

Generated by: LCOV version 1.11