LCOV - code coverage report
Current view: top level - src - name.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 119 69.7 %
Date: 2016-12-01 18:28:20 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* name.c - Object to access GeneralNames etc.
       2             :  * Copyright (C) 2002, 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             : #include <config.h>
      32             : #include <stdio.h>
      33             : #include <stdlib.h>
      34             : #include <string.h>
      35             : #include <assert.h>
      36             : #include <errno.h>
      37             : 
      38             : #include "util.h"
      39             : #include "asn1-func.h"
      40             : #include "convert.h"
      41             : #include "ber-help.h"
      42             : 
      43             : 
      44             : struct ksba_name_s {
      45             :   int ref_count;
      46             :   int n_names;   /* number of names */
      47             :   char **names;  /* array with the parsed names */
      48             : };
      49             : 
      50             : 
      51             : /* Also this is a public function it is not yet usable becuase we
      52             :    don't have a way to set real information.  */
      53             : gpg_error_t
      54           4 : ksba_name_new (ksba_name_t *r_name)
      55             : {
      56           4 :   *r_name = xtrycalloc (1, sizeof **r_name);
      57           4 :   if (!*r_name)
      58           0 :     return gpg_error_from_errno (errno);
      59           4 :   (*r_name)->ref_count++;
      60             : 
      61           4 :   return 0;
      62             : }
      63             : 
      64             : void
      65           0 : ksba_name_ref (ksba_name_t name)
      66             : {
      67           0 :   if (!name)
      68           0 :     fprintf (stderr, "BUG: ksba_name_ref for NULL\n");
      69             :   else
      70           0 :     ++name->ref_count;
      71           0 : }
      72             : 
      73             : 
      74             : void
      75           6 : ksba_name_release (ksba_name_t name)
      76             : {
      77             :   int i;
      78             : 
      79           6 :   if (!name)
      80           2 :     return;
      81           4 :   if (name->ref_count < 1)
      82             :     {
      83           0 :       fprintf (stderr, "BUG: trying to release an already released name\n");
      84           0 :       return;
      85             :     }
      86           4 :   if (--name->ref_count)
      87           0 :     return;
      88             : 
      89           8 :   for (i=0; i < name->n_names; i++)
      90           4 :     xfree (name->names[i]);
      91           4 :   xfree (name->names);
      92           4 :   name->n_names = 0;
      93           4 :   xfree (name);
      94             : }
      95             : 
      96             : 
      97             : /* This is an internal function to create an ksba_name_t object from an
      98             :    DER encoded image which must point to an GeneralNames object */
      99             : gpg_error_t
     100           4 : _ksba_name_new_from_der (ksba_name_t *r_name,
     101             :                          const unsigned char *image, size_t imagelen)
     102             : {
     103             :   gpg_error_t err;
     104             :   ksba_name_t name;
     105             :   struct tag_info ti;
     106             :   const unsigned char *der;
     107             :   size_t derlen;
     108             :   int n;
     109             :   char *p;
     110             : 
     111           4 :   if (!r_name || !image)
     112           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     113             : 
     114           4 :   *r_name = NULL;
     115             : 
     116             :   /* Count and check for encoding errors - we won't do this again
     117             :      during the second pass */
     118           4 :   der = image;
     119           4 :   derlen = imagelen;
     120           4 :   n = 0;
     121          12 :   while (derlen)
     122             :     {
     123           4 :       err = _ksba_ber_parse_tl (&der, &derlen, &ti);
     124           4 :       if (err)
     125           0 :         return err;
     126           4 :       if (ti.class != CLASS_CONTEXT)
     127           0 :         return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
     128           4 :       if (ti.ndef)
     129           0 :         return gpg_error (GPG_ERR_NOT_DER_ENCODED);
     130           4 :       if (derlen < ti.length)
     131           0 :         return gpg_error (GPG_ERR_BAD_BER);
     132           4 :       switch (ti.tag)
     133             :         {
     134             :         case 1: /* rfc822Name - this is an imlicit IA5_STRING */
     135             :         case 4: /* Name */
     136             :         case 6: /* URI */
     137           4 :           n++;
     138           4 :           break;
     139             :         default:
     140           0 :           break;
     141             :         }
     142             : 
     143             :       /* advance pointer */
     144           4 :       der += ti.length;
     145           4 :       derlen -= ti.length;
     146             :     }
     147             : 
     148             :   /* allocate array and set all slots to NULL for easier error recovery */
     149           4 :   err = ksba_name_new (&name);
     150           4 :   if (err)
     151           0 :     return err;
     152           4 :   if (!n)
     153           0 :     return 0; /* empty GeneralNames */
     154           4 :   name->names = xtrycalloc (n, sizeof *name->names);
     155           4 :   if (!name->names)
     156             :     {
     157           0 :       ksba_name_release (name);
     158           0 :       return gpg_error (GPG_ERR_ENOMEM);
     159             :     }
     160           4 :   name->n_names = n;
     161             : 
     162             :   /* start the second pass */
     163           4 :   der = image;
     164           4 :   derlen = imagelen;
     165           4 :   n = 0;
     166          12 :   while (derlen)
     167             :     {
     168             :       char numbuf[21];
     169             : 
     170           4 :       err = _ksba_ber_parse_tl (&der, &derlen, &ti);
     171           4 :       assert (!err);
     172           4 :       switch (ti.tag)
     173             :         {
     174             :         case 1: /* rfc822Name - this is an imlicit IA5_STRING */
     175           0 :           p = name->names[n] = xtrymalloc (ti.length+3);
     176           0 :           if (!p)
     177             :             {
     178           0 :               ksba_name_release (name);
     179           0 :               return gpg_error (GPG_ERR_ENOMEM);
     180             :             }
     181           0 :           *p++ = '<';
     182           0 :           memcpy (p, der, ti.length);
     183           0 :           p += ti.length;
     184           0 :           *p++ = '>';
     185           0 :           *p = 0;
     186           0 :           n++;
     187           0 :           break;
     188             :         case 4: /* Name */
     189           2 :           err = _ksba_derdn_to_str (der, ti.length, &p);
     190           2 :           if (err)
     191           0 :             return err; /* FIXME: we need to release some of the memory */
     192           2 :           name->names[n++] = p;
     193           2 :           break;
     194             :         case 6: /* URI */
     195           2 :           sprintf (numbuf, "%u:", (unsigned int)ti.length);
     196           2 :           p = name->names[n] = xtrymalloc (1+5+strlen (numbuf)
     197             :                                            + ti.length +1+1);
     198           2 :           if (!p)
     199             :             {
     200           0 :               ksba_name_release (name);
     201           0 :               return gpg_error (GPG_ERR_ENOMEM);
     202             :             }
     203           2 :           p = stpcpy (p, "(3:uri");
     204           2 :           p = stpcpy (p, numbuf);
     205           2 :           memcpy (p, der, ti.length);
     206           2 :           p += ti.length;
     207           2 :           *p++ = ')';
     208           2 :           *p = 0; /* extra safeguard null */
     209           2 :           n++;
     210           2 :           break;
     211             :         default:
     212           0 :           break;
     213             :         }
     214             : 
     215             :       /* advance pointer */
     216           4 :       der += ti.length;
     217           4 :       derlen -= ti.length;
     218             :     }
     219           4 :   *r_name = name;
     220           4 :   return 0;
     221             : }
     222             : 
     223             : 
     224             : /* By iterating IDX up starting with 0, this function returns the all
     225             :    General Names stored in NAME. The format of the returned name is
     226             :    either a RFC-2253 formated one which can be detected by checking
     227             :    whether the first character is letter or a digit.  RFC 2822 conform
     228             :    email addresses are returned enclosed in angle brackets, the
     229             :    opening angle bracket should be used to detect this.  Other formats
     230             :    are returned as an S-Expression in canonical format, so a opening
     231             :    parenthesis may be used to detect this encoding, in this case the
     232             :    name may include binary null characters, so strlen might return a
     233             :    length shorter than actually used, the real length is implictly
     234             :    given by the structure of the S-Exp, an extra null is appended for
     235             :    safety reasons.  One common format return is probably an Universal
     236             :    Resource Identifier which has the S-expression: "(uri <urivalue>)".
     237             : 
     238             :    The return string has the same lifetime as NAME. */
     239             : const char *
     240          12 : ksba_name_enum (ksba_name_t name, int idx)
     241             : {
     242          12 :   if (!name || idx < 0)
     243           0 :     return NULL;
     244          12 :   if (idx >= name->n_names)
     245           4 :     return NULL;  /* end of list */
     246             : 
     247           8 :   return name->names[idx];
     248             : }
     249             : 
     250             : /* Convenience function to return names representing an URI.  Caller
     251             :    must free the return value.  Note that this function should not be
     252             :    used for enumeration */
     253             : char *
     254           4 : ksba_name_get_uri (ksba_name_t name, int idx)
     255             : {
     256           4 :   const char *s = ksba_name_enum (name, idx);
     257             :   int n;
     258             :   char *buf;
     259             : 
     260           4 :   if (!s || strncmp (s, "(3:uri", 6))
     261           2 :     return NULL;  /* we do only return URIs */
     262           2 :   s += 6;
     263           6 :   for (n=0; *s && *s != ':' && digitp (s); s++)
     264           4 :     n = n*10 + atoi_1 (s);
     265           2 :   if (!n || *s != ':')
     266           0 :     return NULL; /* oops */
     267           2 :   s++;
     268           2 :   buf = xtrymalloc (n+1);
     269           2 :   if (buf)
     270             :     {
     271           2 :       memcpy (buf, s, n);
     272           2 :       buf[n] = 0;
     273             :     }
     274           2 :   return buf;
     275             : }

Generated by: LCOV version 1.11