Imported Upstream version 1.3.4
[platform/upstream/libksba.git] / src / name.c
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 ksba_name_new (ksba_name_t *r_name)
55 {
56   *r_name = xtrycalloc (1, sizeof **r_name);
57   if (!*r_name)
58     return gpg_error_from_errno (errno);
59   (*r_name)->ref_count++;
60
61   return 0;
62 }
63
64 void
65 ksba_name_ref (ksba_name_t name)
66 {
67   if (!name)
68     fprintf (stderr, "BUG: ksba_name_ref for NULL\n");
69   else
70     ++name->ref_count;
71 }
72
73
74 void
75 ksba_name_release (ksba_name_t name)
76 {
77   int i;
78
79   if (!name)
80     return;
81   if (name->ref_count < 1)
82     {
83       fprintf (stderr, "BUG: trying to release an already released name\n");
84       return;
85     }
86   if (--name->ref_count)
87     return;
88
89   for (i=0; i < name->n_names; i++)
90     xfree (name->names[i]);
91   xfree (name->names);
92   name->n_names = 0;
93   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 _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   if (!r_name || !image)
112     return gpg_error (GPG_ERR_INV_VALUE);
113
114   *r_name = NULL;
115
116   /* Count and check for encoding errors - we won't do this again
117      during the second pass */
118   der = image;
119   derlen = imagelen;
120   n = 0;
121   while (derlen)
122     {
123       err = _ksba_ber_parse_tl (&der, &derlen, &ti);
124       if (err)
125         return err;
126       if (ti.class != CLASS_CONTEXT)
127         return gpg_error (GPG_ERR_INV_CERT_OBJ); /* we expected a tag */
128       if (ti.ndef)
129         return gpg_error (GPG_ERR_NOT_DER_ENCODED);
130       if (derlen < ti.length)
131         return gpg_error (GPG_ERR_BAD_BER);
132       switch (ti.tag)
133         {
134         case 1: /* rfc822Name - this is an imlicit IA5_STRING */
135         case 4: /* Name */
136         case 6: /* URI */
137           n++;
138           break;
139         default:
140           break;
141         }
142
143       /* advance pointer */
144       der += ti.length;
145       derlen -= ti.length;
146     }
147
148   /* allocate array and set all slots to NULL for easier error recovery */
149   err = ksba_name_new (&name);
150   if (err)
151     return err;
152   if (!n)
153     return 0; /* empty GeneralNames */
154   name->names = xtrycalloc (n, sizeof *name->names);
155   if (!name->names)
156     {
157       ksba_name_release (name);
158       return gpg_error (GPG_ERR_ENOMEM);
159     }
160   name->n_names = n;
161
162   /* start the second pass */
163   der = image;
164   derlen = imagelen;
165   n = 0;
166   while (derlen)
167     {
168       char numbuf[21];
169
170       err = _ksba_ber_parse_tl (&der, &derlen, &ti);
171       assert (!err);
172       switch (ti.tag)
173         {
174         case 1: /* rfc822Name - this is an imlicit IA5_STRING */
175           p = name->names[n] = xtrymalloc (ti.length+3);
176           if (!p)
177             {
178               ksba_name_release (name);
179               return gpg_error (GPG_ERR_ENOMEM);
180             }
181           *p++ = '<';
182           memcpy (p, der, ti.length);
183           p += ti.length;
184           *p++ = '>';
185           *p = 0;
186           n++;
187           break;
188         case 4: /* Name */
189           err = _ksba_derdn_to_str (der, ti.length, &p);
190           if (err)
191             return err; /* FIXME: we need to release some of the memory */
192           name->names[n++] = p;
193           break;
194         case 6: /* URI */
195           sprintf (numbuf, "%u:", (unsigned int)ti.length);
196           p = name->names[n] = xtrymalloc (1+5+strlen (numbuf)
197                                            + ti.length +1+1);
198           if (!p)
199             {
200               ksba_name_release (name);
201               return gpg_error (GPG_ERR_ENOMEM);
202             }
203           p = stpcpy (p, "(3:uri");
204           p = stpcpy (p, numbuf);
205           memcpy (p, der, ti.length);
206           p += ti.length;
207           *p++ = ')';
208           *p = 0; /* extra safeguard null */
209           n++;
210           break;
211         default:
212           break;
213         }
214
215       /* advance pointer */
216       der += ti.length;
217       derlen -= ti.length;
218     }
219   *r_name = name;
220   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 ksba_name_enum (ksba_name_t name, int idx)
241 {
242   if (!name || idx < 0)
243     return NULL;
244   if (idx >= name->n_names)
245     return NULL;  /* end of list */
246
247   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 ksba_name_get_uri (ksba_name_t name, int idx)
255 {
256   const char *s = ksba_name_enum (name, idx);
257   int n;
258   char *buf;
259
260   if (!s || strncmp (s, "(3:uri", 6))
261     return NULL;  /* we do only return URIs */
262   s += 6;
263   for (n=0; *s && *s != ':' && digitp (s); s++)
264     n = n*10 + atoi_1 (s);
265   if (!n || *s != ':')
266     return NULL; /* oops */
267   s++;
268   buf = xtrymalloc (n+1);
269   if (buf)
270     {
271       memcpy (buf, s, n);
272       buf[n] = 0;
273     }
274   return buf;
275 }