LCOV - code coverage report
Current view: top level - egg - egg-dn.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.4 % 147 127
Test Date: 2024-05-07 18:02:03 Functions: 90.9 % 11 10

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* egg-asn1.c - ASN.1 helper routines
       3              : 
       4              :    Copyright (C) 2007 Stefan Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library 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 GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #include "egg-asn1-defs.h"
      26              : #include "egg-asn1x.h"
      27              : #include "egg-dn.h"
      28              : #include "egg-oid.h"
      29              : 
      30              : #include <string.h>
      31              : 
      32              : static const char HEXC[] = "0123456789ABCDEF";
      33              : 
      34              : static gchar*
      35            1 : dn_print_hex_value (GBytes *val)
      36              : {
      37            1 :         const gchar *data = g_bytes_get_data (val, NULL);
      38            1 :         gsize size = g_bytes_get_size (val);
      39            1 :         GString *result = g_string_sized_new (size * 2 + 1);
      40              :         gsize i;
      41              : 
      42              :         g_string_append_c (result, '#');
      43           29 :         for (i = 0; i < size; ++i) {
      44           28 :                 g_string_append_c (result, HEXC[data[i] >> 4 & 0xf]);
      45           28 :                 g_string_append_c (result, HEXC[data[i] & 0xf]);
      46              :         }
      47              : 
      48            1 :         return g_string_free (result, FALSE);
      49              : }
      50              : 
      51              : static gchar*
      52           24 : dn_print_oid_value_parsed (GQuark oid,
      53              :                            guint flags,
      54              :                            GNode *val)
      55              : {
      56              :         GNode *asn1, *node;
      57              :         GBytes *value;
      58              :         const gchar *data;
      59              :         gsize size;
      60              :         gchar *result;
      61              : 
      62           24 :         g_assert (val != NULL);
      63              : 
      64           24 :         asn1 = egg_asn1x_create_quark (pkix_asn1_tab, oid);
      65           24 :         g_return_val_if_fail (asn1, NULL);
      66              : 
      67           24 :         if (!egg_asn1x_get_any_into (val, asn1)) {
      68            0 :                 g_message ("couldn't decode value for OID: %s: %s",
      69              :                            g_quark_to_string (oid), egg_asn1x_message (asn1));
      70            0 :                 egg_asn1x_destroy (asn1);
      71            0 :                 return NULL;
      72              :         }
      73              : 
      74              :         /*
      75              :          * If it's a choice element, then we have to read depending
      76              :          * on what's there.
      77              :          */
      78           24 :         if (flags & EGG_OID_IS_CHOICE)
      79           20 :                 node = egg_asn1x_get_choice (asn1);
      80              :         else
      81            4 :                 node = asn1;
      82              : 
      83           24 :         value = egg_asn1x_get_value_raw (node);
      84           24 :         data = g_bytes_get_data (value, &size);
      85              : 
      86              :         /*
      87              :          * Now we make sure it's UTF-8.
      88              :          */
      89              : 
      90           24 :         if (!value) {
      91            0 :                 g_message ("couldn't read value for OID: %s", g_quark_to_string (oid));
      92            0 :                 result = NULL;
      93              : 
      94           24 :         } else if (!g_utf8_validate (data, size, NULL)) {
      95            0 :                 result = dn_print_hex_value (value);
      96              : 
      97              :         } else {
      98           24 :                 result = g_strndup (data, size);
      99              :         }
     100              : 
     101           24 :         g_bytes_unref (value);
     102           24 :         egg_asn1x_destroy (asn1);
     103              : 
     104           24 :         return result;
     105              : }
     106              : 
     107              : static gchar*
     108           25 : dn_print_oid_value (GQuark oid,
     109              :                     guint flags,
     110              :                     GNode *val)
     111              : {
     112              :         GBytes *der;
     113              :         gchar *value;
     114              : 
     115           25 :         g_assert (val != NULL);
     116              : 
     117           25 :         if (flags & EGG_OID_PRINTABLE) {
     118           24 :                 value = dn_print_oid_value_parsed (oid, flags, val);
     119           24 :                 if (value != NULL)
     120           24 :                         return value;
     121              :         }
     122              : 
     123            1 :         der = egg_asn1x_get_element_raw (val);
     124            1 :         value = dn_print_hex_value (der);
     125            1 :         g_bytes_unref (der);
     126              : 
     127            1 :         return value;
     128              : }
     129              : 
     130              : static gchar*
     131            7 : dn_parse_rdn (GNode *asn)
     132              : {
     133              :         const gchar *name;
     134              :         guint flags;
     135              :         GQuark oid;
     136              :         GNode *value;
     137              :         gchar *display;
     138              :         gchar *result;
     139              : 
     140            7 :         g_assert (asn);
     141              : 
     142            7 :         oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "type", NULL));
     143            7 :         g_return_val_if_fail (oid, NULL);
     144              : 
     145            7 :         flags = egg_oid_get_flags (oid);
     146            7 :         name = egg_oid_get_name (oid);
     147              : 
     148            7 :         value = egg_asn1x_node (asn, "value", NULL);
     149            7 :         g_return_val_if_fail (value, NULL);
     150              : 
     151            7 :         display = dn_print_oid_value (oid, flags, value);
     152            7 :         result = g_strconcat ((flags & EGG_OID_PRINTABLE) ? name : g_quark_to_string (oid),
     153              :                               "=", display, NULL);
     154            7 :         g_free (display);
     155              : 
     156            7 :         return result;
     157              : }
     158              : 
     159              : gchar*
     160            1 : egg_dn_read (GNode* asn)
     161              : {
     162            1 :         gboolean done = FALSE;
     163              :         GString *result;
     164              :         GNode *node;
     165              :         gchar *rdn;
     166              :         gint i, j;
     167              : 
     168            1 :         g_return_val_if_fail (asn, NULL);
     169              : 
     170            1 :         result = g_string_sized_new (64);
     171              : 
     172              :         /* Each (possibly multi valued) RDN */
     173            9 :         for (i = 1; !done; ++i) {
     174              : 
     175              :                 /* Each type=value pair of an RDN */
     176            8 :                 for (j = 1; TRUE; ++j) {
     177           15 :                         node = egg_asn1x_node (asn, i, j, NULL);
     178           15 :                         if (!node) {
     179            8 :                                 done = j == 1;
     180            8 :                                 break;
     181              :                         }
     182              : 
     183            7 :                         rdn = dn_parse_rdn (node);
     184            7 :                         g_return_val_if_fail (rdn, NULL);
     185              : 
     186              :                         /* Account for multi valued RDNs */
     187            7 :                         if (j > 1)
     188            0 :                                 g_string_append (result, "+");
     189            7 :                         else if (i > 1)
     190           12 :                                 g_string_append (result, ", ");
     191              : 
     192              :                         g_string_append (result, rdn);
     193            7 :                         g_free (rdn);
     194              :                 }
     195              :         }
     196              : 
     197              :         /* Returns null when string is empty */
     198            1 :         return g_string_free (result, (result->len == 0));
     199              : }
     200              : 
     201              : gchar*
     202           12 : egg_dn_read_part (GNode *asn, const gchar *match)
     203              : {
     204           12 :         gboolean done = FALSE;
     205              :         const gchar *name;
     206              :         GNode *node;
     207              :         GQuark oid;
     208              :         gint i, j;
     209              : 
     210           12 :         g_return_val_if_fail (asn, NULL);
     211           12 :         g_return_val_if_fail (match, NULL);
     212              : 
     213              :         /* Each (possibly multi valued) RDN */
     214           57 :         for (i = 1; !done; ++i) {
     215              : 
     216              :                 /* Each type=value pair of an RDN */
     217           54 :                 for (j = 1; TRUE; ++j) {
     218           96 :                         node = egg_asn1x_node (asn, i, j, "type", NULL);
     219           96 :                         if (!node) {
     220           45 :                                 done = j == 1;
     221           45 :                                 break;
     222              :                         }
     223              : 
     224           51 :                         oid = egg_asn1x_get_oid_as_quark (node);
     225           51 :                         g_return_val_if_fail (oid, NULL);
     226              : 
     227              :                         /* Does it match either the OID or the displayable? */
     228           51 :                         if (g_ascii_strcasecmp (g_quark_to_string (oid), match) != 0) {
     229           50 :                                 name = egg_oid_get_name (oid);
     230           50 :                                 if (g_ascii_strcasecmp (name, match) != 0)
     231           42 :                                         continue;
     232              :                         }
     233              : 
     234            9 :                         node = egg_asn1x_node (asn, i, j, "value", NULL);
     235            9 :                         g_return_val_if_fail (node, NULL);
     236              : 
     237            9 :                         return dn_print_oid_value (oid, egg_oid_get_flags (oid), node);
     238              :                 }
     239              :         }
     240              : 
     241            3 :         return NULL;
     242              : }
     243              : 
     244              : gboolean
     245            1 : egg_dn_parse (GNode *asn, EggDnCallback callback, gpointer user_data)
     246              : {
     247            1 :         gboolean done = FALSE;
     248              :         GNode *node;
     249              :         GQuark oid;
     250              :         guint i, j;
     251              : 
     252            1 :         g_return_val_if_fail (asn, FALSE);
     253              : 
     254              :         /* Each (possibly multi valued) RDN */
     255            9 :         for (i = 1; !done; ++i) {
     256              : 
     257              :                 /* Each type=value pair of an RDN */
     258            8 :                 for (j = 1; TRUE; ++j) {
     259              : 
     260              :                         /* Dig out the type */
     261           15 :                         node = egg_asn1x_node (asn, i, j, "type", NULL);
     262           15 :                         if (!node) {
     263            8 :                                 done = j == 1;
     264            8 :                                 break;
     265              :                         }
     266              : 
     267            7 :                         oid = egg_asn1x_get_oid_as_quark (node);
     268            7 :                         g_return_val_if_fail (oid, FALSE);
     269              : 
     270              :                         /* Dig out the value */
     271            7 :                         node = egg_asn1x_node (asn, i, j, "value", NULL);
     272            7 :                         if (!node) {
     273            0 :                                 done = j == 1;
     274            0 :                                 break;
     275              :                         }
     276              : 
     277            7 :                         if (callback)
     278            7 :                                 (callback) (i, oid, node, user_data);
     279              :                 }
     280              :         }
     281              : 
     282            1 :         return i > 1;
     283              : }
     284              : 
     285              : gchar *
     286            9 : egg_dn_print_value (GQuark oid,
     287              :                     GNode *value)
     288              : {
     289            9 :         g_return_val_if_fail (oid != 0, NULL);
     290            9 :         g_return_val_if_fail (value != NULL, NULL);
     291              : 
     292            9 :         return dn_print_oid_value (oid, egg_oid_get_flags (oid), value);
     293              : }
     294              : 
     295              : static gboolean
     296            0 : is_ascii_string (const gchar *string)
     297              : {
     298            0 :         const gchar *p = string;
     299              : 
     300            0 :         g_return_val_if_fail (string != NULL, FALSE);
     301              : 
     302            0 :         for (p = string; *p != '\0'; p++) {
     303            0 :                 if (!g_ascii_isspace (*p) && *p < ' ')
     304            0 :                         return FALSE;
     305              :         }
     306              : 
     307            0 :         return TRUE;
     308              : }
     309              : 
     310              : static gboolean
     311            5 : is_printable_string (const gchar *string)
     312              : {
     313            5 :         const gchar *p = string;
     314              : 
     315            5 :         g_return_val_if_fail (string != NULL, FALSE);
     316              : 
     317          100 :         for (p = string; *p != '\0'; p++) {
     318           95 :                 if (!g_ascii_isalnum (*p) && !strchr (" '()+,-./:=?", *p))
     319            0 :                         return FALSE;
     320              :         }
     321              : 
     322            5 :         return TRUE;
     323              : }
     324              : 
     325              : void
     326            7 : egg_dn_add_string_part (GNode *asn,
     327              :                         GQuark oid,
     328              :                         const gchar *string)
     329              : {
     330              :         GNode *node;
     331              :         GNode *value;
     332              :         GNode *val;
     333              :         guint flags;
     334              : 
     335            7 :         g_return_if_fail (asn != NULL);
     336            7 :         g_return_if_fail (oid != 0);
     337            7 :         g_return_if_fail (string != NULL);
     338              : 
     339            7 :         flags = egg_oid_get_flags (oid);
     340            7 :         g_return_if_fail (flags & EGG_OID_PRINTABLE);
     341              : 
     342              :         /* Add the RelativeDistinguishedName */
     343            7 :         node = egg_asn1x_append (asn);
     344              : 
     345              :         /* Add the AttributeTypeAndValue */
     346            7 :         node = egg_asn1x_append (node);
     347              : 
     348            7 :         egg_asn1x_set_oid_as_quark (egg_asn1x_node (node, "type", NULL), oid);
     349              : 
     350            7 :         value = egg_asn1x_create_quark (pkix_asn1_tab, oid);
     351              : 
     352            7 :         if (egg_asn1x_type (value) == EGG_ASN1X_CHOICE) {
     353            5 :                 if (is_printable_string (string))
     354            5 :                         val = egg_asn1x_node (value, "printableString", NULL);
     355            0 :                 else if (is_ascii_string (string))
     356            0 :                         val = egg_asn1x_node (value, "ia5String", NULL);
     357              :                 else
     358            0 :                         val = egg_asn1x_node (value, "utf8String", NULL);
     359            5 :                 egg_asn1x_set_choice (value, val);
     360              :         } else {
     361            2 :                 val = value;
     362              :         }
     363              : 
     364            7 :         egg_asn1x_set_string_as_utf8 (val, g_strdup (string), g_free);
     365              : 
     366            7 :         egg_asn1x_set_any_from (egg_asn1x_node (node, "value", NULL), value);
     367            7 :         egg_asn1x_destroy (value);
     368              : }
        

Generated by: LCOV version 2.0-1