1c19800e8SDoug Rabson /*
2ae771770SStanislav Sedov * Copyright (c) 2004 - 2009 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson * are met:
9c19800e8SDoug Rabson *
10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson *
13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson *
17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson * without specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson * SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34c19800e8SDoug Rabson #include "hx_locl.h"
35ae771770SStanislav Sedov #include <wind.h>
36ae771770SStanislav Sedov #include "char_map.h"
37c19800e8SDoug Rabson
38c19800e8SDoug Rabson /**
39c19800e8SDoug Rabson * @page page_name PKIX/X.509 Names
40c19800e8SDoug Rabson *
41c19800e8SDoug Rabson * There are several names in PKIX/X.509, GeneralName and Name.
42c19800e8SDoug Rabson *
43c19800e8SDoug Rabson * A Name consists of an ordered list of Relative Distinguished Names
44c19800e8SDoug Rabson * (RDN). Each RDN consists of an unordered list of typed strings. The
45c19800e8SDoug Rabson * types are defined by OID and have long and short description. For
46c19800e8SDoug Rabson * example id-at-commonName (2.5.4.3) have the long name CommonName
47ae771770SStanislav Sedov * and short name CN. The string itself can be of several encoding,
48c19800e8SDoug Rabson * UTF8, UTF16, Teltex string, etc. The type limit what encoding
49c19800e8SDoug Rabson * should be used.
50c19800e8SDoug Rabson *
51c19800e8SDoug Rabson * GeneralName is a broader nametype that can contains al kind of
52c19800e8SDoug Rabson * stuff like Name, IP addresses, partial Name, etc.
53c19800e8SDoug Rabson *
54c19800e8SDoug Rabson * Name is mapped into a hx509_name object.
55c19800e8SDoug Rabson *
56c19800e8SDoug Rabson * Parse and string name into a hx509_name object with hx509_parse_name(),
57c19800e8SDoug Rabson * make it back into string representation with hx509_name_to_string().
58c19800e8SDoug Rabson *
59c19800e8SDoug Rabson * Name string are defined rfc2253, rfc1779 and X.501.
60c19800e8SDoug Rabson *
61c19800e8SDoug Rabson * See the library functions here: @ref hx509_name
62c19800e8SDoug Rabson */
63c19800e8SDoug Rabson
64c19800e8SDoug Rabson static const struct {
65c19800e8SDoug Rabson const char *n;
66ae771770SStanislav Sedov const heim_oid *o;
67ae771770SStanislav Sedov wind_profile_flags flags;
68c19800e8SDoug Rabson } no[] = {
69ae771770SStanislav Sedov { "C", &asn1_oid_id_at_countryName, 0 },
70ae771770SStanislav Sedov { "CN", &asn1_oid_id_at_commonName, 0 },
71ae771770SStanislav Sedov { "DC", &asn1_oid_id_domainComponent, 0 },
72ae771770SStanislav Sedov { "L", &asn1_oid_id_at_localityName, 0 },
73ae771770SStanislav Sedov { "O", &asn1_oid_id_at_organizationName, 0 },
74ae771770SStanislav Sedov { "OU", &asn1_oid_id_at_organizationalUnitName, 0 },
75ae771770SStanislav Sedov { "S", &asn1_oid_id_at_stateOrProvinceName, 0 },
76ae771770SStanislav Sedov { "STREET", &asn1_oid_id_at_streetAddress, 0 },
77ae771770SStanislav Sedov { "UID", &asn1_oid_id_Userid, 0 },
78ae771770SStanislav Sedov { "emailAddress", &asn1_oid_id_pkcs9_emailAddress, 0 },
79ae771770SStanislav Sedov { "serialNumber", &asn1_oid_id_at_serialNumber, 0 }
80c19800e8SDoug Rabson };
81c19800e8SDoug Rabson
82c19800e8SDoug Rabson static char *
quote_string(const char * f,size_t len,int flags,size_t * rlen)83ae771770SStanislav Sedov quote_string(const char *f, size_t len, int flags, size_t *rlen)
84c19800e8SDoug Rabson {
85c19800e8SDoug Rabson size_t i, j, tolen;
86ae771770SStanislav Sedov const unsigned char *from = (const unsigned char *)f;
87ae771770SStanislav Sedov unsigned char *to;
88c19800e8SDoug Rabson
89c19800e8SDoug Rabson tolen = len * 3 + 1;
90c19800e8SDoug Rabson to = malloc(tolen);
91c19800e8SDoug Rabson if (to == NULL)
92c19800e8SDoug Rabson return NULL;
93c19800e8SDoug Rabson
94c19800e8SDoug Rabson for (i = 0, j = 0; i < len; i++) {
95ae771770SStanislav Sedov unsigned char map = char_map[from[i]] & flags;
96ae771770SStanislav Sedov if (i == 0 && (map & Q_RFC2253_QUOTE_FIRST)) {
97c19800e8SDoug Rabson to[j++] = '\\';
98c19800e8SDoug Rabson to[j++] = from[i];
99ae771770SStanislav Sedov } else if ((i + 1) == len && (map & Q_RFC2253_QUOTE_LAST)) {
100ae771770SStanislav Sedov
101ae771770SStanislav Sedov to[j++] = '\\';
102c19800e8SDoug Rabson to[j++] = from[i];
103ae771770SStanislav Sedov } else if (map & Q_RFC2253_QUOTE) {
104ae771770SStanislav Sedov to[j++] = '\\';
105ae771770SStanislav Sedov to[j++] = from[i];
106ae771770SStanislav Sedov } else if (map & Q_RFC2253_HEX) {
107ae771770SStanislav Sedov int l = snprintf((char *)&to[j], tolen - j - 1,
108c19800e8SDoug Rabson "#%02x", (unsigned char)from[i]);
109c19800e8SDoug Rabson j += l;
110ae771770SStanislav Sedov } else {
111ae771770SStanislav Sedov to[j++] = from[i];
112c19800e8SDoug Rabson }
113c19800e8SDoug Rabson }
114c19800e8SDoug Rabson to[j] = '\0';
115c19800e8SDoug Rabson assert(j < tolen);
116c19800e8SDoug Rabson *rlen = j;
117ae771770SStanislav Sedov return (char *)to;
118c19800e8SDoug Rabson }
119c19800e8SDoug Rabson
120c19800e8SDoug Rabson
121c19800e8SDoug Rabson static int
append_string(char ** str,size_t * total_len,const char * ss,size_t len,int quote)122c19800e8SDoug Rabson append_string(char **str, size_t *total_len, const char *ss,
123c19800e8SDoug Rabson size_t len, int quote)
124c19800e8SDoug Rabson {
125c19800e8SDoug Rabson char *s, *qs;
126c19800e8SDoug Rabson
127c19800e8SDoug Rabson if (quote)
128ae771770SStanislav Sedov qs = quote_string(ss, len, Q_RFC2253, &len);
129c19800e8SDoug Rabson else
130c19800e8SDoug Rabson qs = rk_UNCONST(ss);
131c19800e8SDoug Rabson
132c19800e8SDoug Rabson s = realloc(*str, len + *total_len + 1);
133c19800e8SDoug Rabson if (s == NULL)
134c19800e8SDoug Rabson _hx509_abort("allocation failure"); /* XXX */
135c19800e8SDoug Rabson memcpy(s + *total_len, qs, len);
136c19800e8SDoug Rabson if (qs != ss)
137c19800e8SDoug Rabson free(qs);
138c19800e8SDoug Rabson s[*total_len + len] = '\0';
139c19800e8SDoug Rabson *str = s;
140c19800e8SDoug Rabson *total_len += len;
141c19800e8SDoug Rabson return 0;
142c19800e8SDoug Rabson }
143c19800e8SDoug Rabson
144c19800e8SDoug Rabson static char *
oidtostring(const heim_oid * type)145c19800e8SDoug Rabson oidtostring(const heim_oid *type)
146c19800e8SDoug Rabson {
147c19800e8SDoug Rabson char *s;
148c19800e8SDoug Rabson size_t i;
149c19800e8SDoug Rabson
150c19800e8SDoug Rabson for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
151ae771770SStanislav Sedov if (der_heim_oid_cmp(no[i].o, type) == 0)
152c19800e8SDoug Rabson return strdup(no[i].n);
153c19800e8SDoug Rabson }
154c19800e8SDoug Rabson if (der_print_heim_oid(type, '.', &s) != 0)
155c19800e8SDoug Rabson return NULL;
156c19800e8SDoug Rabson return s;
157c19800e8SDoug Rabson }
158c19800e8SDoug Rabson
159c19800e8SDoug Rabson static int
stringtooid(const char * name,size_t len,heim_oid * oid)160c19800e8SDoug Rabson stringtooid(const char *name, size_t len, heim_oid *oid)
161c19800e8SDoug Rabson {
162ae771770SStanislav Sedov int ret;
163ae771770SStanislav Sedov size_t i;
164c19800e8SDoug Rabson char *s;
165c19800e8SDoug Rabson
166c19800e8SDoug Rabson memset(oid, 0, sizeof(*oid));
167c19800e8SDoug Rabson
168c19800e8SDoug Rabson for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
169c19800e8SDoug Rabson if (strncasecmp(no[i].n, name, len) == 0)
170ae771770SStanislav Sedov return der_copy_oid(no[i].o, oid);
171c19800e8SDoug Rabson }
172c19800e8SDoug Rabson s = malloc(len + 1);
173c19800e8SDoug Rabson if (s == NULL)
174c19800e8SDoug Rabson return ENOMEM;
175c19800e8SDoug Rabson memcpy(s, name, len);
176c19800e8SDoug Rabson s[len] = '\0';
177c19800e8SDoug Rabson ret = der_parse_heim_oid(s, ".", oid);
178c19800e8SDoug Rabson free(s);
179c19800e8SDoug Rabson return ret;
180c19800e8SDoug Rabson }
181c19800e8SDoug Rabson
182c19800e8SDoug Rabson /**
183c19800e8SDoug Rabson * Convert the hx509 name object into a printable string.
184c19800e8SDoug Rabson * The resulting string should be freed with free().
185c19800e8SDoug Rabson *
186c19800e8SDoug Rabson * @param name name to print
187c19800e8SDoug Rabson * @param str the string to return
188c19800e8SDoug Rabson *
189c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
190c19800e8SDoug Rabson *
191c19800e8SDoug Rabson * @ingroup hx509_name
192c19800e8SDoug Rabson */
193c19800e8SDoug Rabson
194c19800e8SDoug Rabson int
hx509_name_to_string(const hx509_name name,char ** str)195c19800e8SDoug Rabson hx509_name_to_string(const hx509_name name, char **str)
196c19800e8SDoug Rabson {
197c19800e8SDoug Rabson return _hx509_Name_to_string(&name->der_name, str);
198c19800e8SDoug Rabson }
199c19800e8SDoug Rabson
200c19800e8SDoug Rabson int
_hx509_Name_to_string(const Name * n,char ** str)201c19800e8SDoug Rabson _hx509_Name_to_string(const Name *n, char **str)
202c19800e8SDoug Rabson {
203c19800e8SDoug Rabson size_t total_len = 0;
204ae771770SStanislav Sedov size_t i, j, m;
205ae771770SStanislav Sedov int ret;
206c19800e8SDoug Rabson
207c19800e8SDoug Rabson *str = strdup("");
208c19800e8SDoug Rabson if (*str == NULL)
209c19800e8SDoug Rabson return ENOMEM;
210c19800e8SDoug Rabson
211ae771770SStanislav Sedov for (m = n->u.rdnSequence.len; m > 0; m--) {
212ae771770SStanislav Sedov size_t len;
213ae771770SStanislav Sedov i = m - 1;
214c19800e8SDoug Rabson
215c19800e8SDoug Rabson for (j = 0; j < n->u.rdnSequence.val[i].len; j++) {
216c19800e8SDoug Rabson DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value;
217c19800e8SDoug Rabson char *oidname;
218c19800e8SDoug Rabson char *ss;
219c19800e8SDoug Rabson
220c19800e8SDoug Rabson oidname = oidtostring(&n->u.rdnSequence.val[i].val[j].type);
221c19800e8SDoug Rabson
222c19800e8SDoug Rabson switch(ds->element) {
223c19800e8SDoug Rabson case choice_DirectoryString_ia5String:
224ae771770SStanislav Sedov ss = ds->u.ia5String.data;
225ae771770SStanislav Sedov len = ds->u.ia5String.length;
226c19800e8SDoug Rabson break;
227c19800e8SDoug Rabson case choice_DirectoryString_printableString:
228ae771770SStanislav Sedov ss = ds->u.printableString.data;
229ae771770SStanislav Sedov len = ds->u.printableString.length;
230c19800e8SDoug Rabson break;
231c19800e8SDoug Rabson case choice_DirectoryString_utf8String:
232c19800e8SDoug Rabson ss = ds->u.utf8String;
233ae771770SStanislav Sedov len = strlen(ss);
234c19800e8SDoug Rabson break;
235c19800e8SDoug Rabson case choice_DirectoryString_bmpString: {
236ae771770SStanislav Sedov const uint16_t *bmp = ds->u.bmpString.data;
237c19800e8SDoug Rabson size_t bmplen = ds->u.bmpString.length;
238c19800e8SDoug Rabson size_t k;
239c19800e8SDoug Rabson
240ae771770SStanislav Sedov ret = wind_ucs2utf8_length(bmp, bmplen, &k);
241ae771770SStanislav Sedov if (ret)
242ae771770SStanislav Sedov return ret;
243ae771770SStanislav Sedov
244ae771770SStanislav Sedov ss = malloc(k + 1);
245c19800e8SDoug Rabson if (ss == NULL)
246c19800e8SDoug Rabson _hx509_abort("allocation failure"); /* XXX */
247ae771770SStanislav Sedov ret = wind_ucs2utf8(bmp, bmplen, ss, NULL);
248ae771770SStanislav Sedov if (ret) {
249ae771770SStanislav Sedov free(ss);
250ae771770SStanislav Sedov return ret;
251ae771770SStanislav Sedov }
252c19800e8SDoug Rabson ss[k] = '\0';
253ae771770SStanislav Sedov len = k;
254c19800e8SDoug Rabson break;
255c19800e8SDoug Rabson }
256c19800e8SDoug Rabson case choice_DirectoryString_teletexString:
257ae771770SStanislav Sedov ss = ds->u.teletexString;
258ae771770SStanislav Sedov len = strlen(ss);
259c19800e8SDoug Rabson break;
260c19800e8SDoug Rabson case choice_DirectoryString_universalString: {
261ae771770SStanislav Sedov const uint32_t *uni = ds->u.universalString.data;
262c19800e8SDoug Rabson size_t unilen = ds->u.universalString.length;
263c19800e8SDoug Rabson size_t k;
264c19800e8SDoug Rabson
265ae771770SStanislav Sedov ret = wind_ucs4utf8_length(uni, unilen, &k);
266ae771770SStanislav Sedov if (ret)
267ae771770SStanislav Sedov return ret;
268ae771770SStanislav Sedov
269ae771770SStanislav Sedov ss = malloc(k + 1);
270c19800e8SDoug Rabson if (ss == NULL)
271c19800e8SDoug Rabson _hx509_abort("allocation failure"); /* XXX */
272ae771770SStanislav Sedov ret = wind_ucs4utf8(uni, unilen, ss, NULL);
273ae771770SStanislav Sedov if (ret) {
274ae771770SStanislav Sedov free(ss);
275ae771770SStanislav Sedov return ret;
276ae771770SStanislav Sedov }
277c19800e8SDoug Rabson ss[k] = '\0';
278ae771770SStanislav Sedov len = k;
279c19800e8SDoug Rabson break;
280c19800e8SDoug Rabson }
281c19800e8SDoug Rabson default:
282c19800e8SDoug Rabson _hx509_abort("unknown directory type: %d", ds->element);
283c19800e8SDoug Rabson exit(1);
284c19800e8SDoug Rabson }
285c19800e8SDoug Rabson append_string(str, &total_len, oidname, strlen(oidname), 0);
286c19800e8SDoug Rabson free(oidname);
287c19800e8SDoug Rabson append_string(str, &total_len, "=", 1, 0);
288c19800e8SDoug Rabson append_string(str, &total_len, ss, len, 1);
289ae771770SStanislav Sedov if (ds->element == choice_DirectoryString_bmpString ||
290ae771770SStanislav Sedov ds->element == choice_DirectoryString_universalString)
291c19800e8SDoug Rabson {
292c19800e8SDoug Rabson free(ss);
293c19800e8SDoug Rabson }
294c19800e8SDoug Rabson if (j + 1 < n->u.rdnSequence.val[i].len)
295c19800e8SDoug Rabson append_string(str, &total_len, "+", 1, 0);
296c19800e8SDoug Rabson }
297c19800e8SDoug Rabson
298c19800e8SDoug Rabson if (i > 0)
299c19800e8SDoug Rabson append_string(str, &total_len, ",", 1, 0);
300c19800e8SDoug Rabson }
301c19800e8SDoug Rabson return 0;
302c19800e8SDoug Rabson }
303c19800e8SDoug Rabson
304ae771770SStanislav Sedov #define COPYCHARARRAY(_ds,_el,_l,_n) \
305ae771770SStanislav Sedov (_l) = strlen(_ds->u._el); \
306ae771770SStanislav Sedov (_n) = malloc((_l) * sizeof((_n)[0])); \
307ae771770SStanislav Sedov if ((_n) == NULL) \
308ae771770SStanislav Sedov return ENOMEM; \
309ae771770SStanislav Sedov for (i = 0; i < (_l); i++) \
310ae771770SStanislav Sedov (_n)[i] = _ds->u._el[i]
311c19800e8SDoug Rabson
312ae771770SStanislav Sedov
313ae771770SStanislav Sedov #define COPYVALARRAY(_ds,_el,_l,_n) \
314ae771770SStanislav Sedov (_l) = _ds->u._el.length; \
315ae771770SStanislav Sedov (_n) = malloc((_l) * sizeof((_n)[0])); \
316ae771770SStanislav Sedov if ((_n) == NULL) \
317ae771770SStanislav Sedov return ENOMEM; \
318ae771770SStanislav Sedov for (i = 0; i < (_l); i++) \
319ae771770SStanislav Sedov (_n)[i] = _ds->u._el.data[i]
320ae771770SStanislav Sedov
321ae771770SStanislav Sedov #define COPYVOIDARRAY(_ds,_el,_l,_n) \
322ae771770SStanislav Sedov (_l) = _ds->u._el.length; \
323ae771770SStanislav Sedov (_n) = malloc((_l) * sizeof((_n)[0])); \
324ae771770SStanislav Sedov if ((_n) == NULL) \
325ae771770SStanislav Sedov return ENOMEM; \
326ae771770SStanislav Sedov for (i = 0; i < (_l); i++) \
327ae771770SStanislav Sedov (_n)[i] = ((unsigned char *)_ds->u._el.data)[i]
328ae771770SStanislav Sedov
329ae771770SStanislav Sedov
330ae771770SStanislav Sedov
331ae771770SStanislav Sedov static int
dsstringprep(const DirectoryString * ds,uint32_t ** rname,size_t * rlen)332ae771770SStanislav Sedov dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
333c19800e8SDoug Rabson {
334ae771770SStanislav Sedov wind_profile_flags flags;
335ae771770SStanislav Sedov size_t i, len;
336ae771770SStanislav Sedov int ret;
337ae771770SStanislav Sedov uint32_t *name;
338c19800e8SDoug Rabson
339ae771770SStanislav Sedov *rname = NULL;
340ae771770SStanislav Sedov *rlen = 0;
341c19800e8SDoug Rabson
342ae771770SStanislav Sedov switch(ds->element) {
343c19800e8SDoug Rabson case choice_DirectoryString_ia5String:
344ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP;
345ae771770SStanislav Sedov COPYVOIDARRAY(ds, ia5String, len, name);
346ae771770SStanislav Sedov break;
347ae771770SStanislav Sedov case choice_DirectoryString_printableString:
348ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP;
349ae771770SStanislav Sedov flags |= WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE;
350ae771770SStanislav Sedov COPYVOIDARRAY(ds, printableString, len, name);
351c19800e8SDoug Rabson break;
352c19800e8SDoug Rabson case choice_DirectoryString_teletexString:
353ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP_CASE;
354ae771770SStanislav Sedov COPYCHARARRAY(ds, teletexString, len, name);
355c19800e8SDoug Rabson break;
356c19800e8SDoug Rabson case choice_DirectoryString_bmpString:
357ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP;
358ae771770SStanislav Sedov COPYVALARRAY(ds, bmpString, len, name);
359ae771770SStanislav Sedov break;
360ae771770SStanislav Sedov case choice_DirectoryString_universalString:
361ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP;
362ae771770SStanislav Sedov COPYVALARRAY(ds, universalString, len, name);
363ae771770SStanislav Sedov break;
364ae771770SStanislav Sedov case choice_DirectoryString_utf8String:
365ae771770SStanislav Sedov flags = WIND_PROFILE_LDAP;
366ae771770SStanislav Sedov ret = wind_utf8ucs4_length(ds->u.utf8String, &len);
367ae771770SStanislav Sedov if (ret)
368ae771770SStanislav Sedov return ret;
369ae771770SStanislav Sedov name = malloc(len * sizeof(name[0]));
370ae771770SStanislav Sedov if (name == NULL)
371ae771770SStanislav Sedov return ENOMEM;
372ae771770SStanislav Sedov ret = wind_utf8ucs4(ds->u.utf8String, name, &len);
373ae771770SStanislav Sedov if (ret) {
374ae771770SStanislav Sedov free(name);
375ae771770SStanislav Sedov return ret;
376ae771770SStanislav Sedov }
377c19800e8SDoug Rabson break;
378c19800e8SDoug Rabson default:
379ae771770SStanislav Sedov _hx509_abort("unknown directory type: %d", ds->element);
380ae771770SStanislav Sedov }
381ae771770SStanislav Sedov
382ae771770SStanislav Sedov *rlen = len;
383ae771770SStanislav Sedov /* try a couple of times to get the length right, XXX gross */
384ae771770SStanislav Sedov for (i = 0; i < 4; i++) {
385ae771770SStanislav Sedov *rlen = *rlen * 2;
386ae771770SStanislav Sedov *rname = malloc(*rlen * sizeof((*rname)[0]));
387ae771770SStanislav Sedov
388ae771770SStanislav Sedov ret = wind_stringprep(name, len, *rname, rlen, flags);
389ae771770SStanislav Sedov if (ret == WIND_ERR_OVERRUN) {
390ae771770SStanislav Sedov free(*rname);
391ae771770SStanislav Sedov *rname = NULL;
392ae771770SStanislav Sedov continue;
393ae771770SStanislav Sedov } else
394c19800e8SDoug Rabson break;
395c19800e8SDoug Rabson }
396ae771770SStanislav Sedov free(name);
397ae771770SStanislav Sedov if (ret) {
398ae771770SStanislav Sedov if (*rname)
399ae771770SStanislav Sedov free(*rname);
400ae771770SStanislav Sedov *rname = NULL;
401ae771770SStanislav Sedov *rlen = 0;
402ae771770SStanislav Sedov return ret;
403ae771770SStanislav Sedov }
404ae771770SStanislav Sedov
405ae771770SStanislav Sedov return 0;
406c19800e8SDoug Rabson }
407c19800e8SDoug Rabson
408c19800e8SDoug Rabson int
_hx509_name_ds_cmp(const DirectoryString * ds1,const DirectoryString * ds2,int * diff)409ae771770SStanislav Sedov _hx509_name_ds_cmp(const DirectoryString *ds1,
410ae771770SStanislav Sedov const DirectoryString *ds2,
411ae771770SStanislav Sedov int *diff)
412c19800e8SDoug Rabson {
413ae771770SStanislav Sedov uint32_t *ds1lp, *ds2lp;
414ae771770SStanislav Sedov size_t ds1len, ds2len, i;
415ae771770SStanislav Sedov int ret;
416c19800e8SDoug Rabson
417ae771770SStanislav Sedov ret = dsstringprep(ds1, &ds1lp, &ds1len);
418ae771770SStanislav Sedov if (ret)
419ae771770SStanislav Sedov return ret;
420ae771770SStanislav Sedov ret = dsstringprep(ds2, &ds2lp, &ds2len);
421ae771770SStanislav Sedov if (ret) {
422ae771770SStanislav Sedov free(ds1lp);
423ae771770SStanislav Sedov return ret;
424ae771770SStanislav Sedov }
425ae771770SStanislav Sedov
426ae771770SStanislav Sedov if (ds1len != ds2len)
427ae771770SStanislav Sedov *diff = ds1len - ds2len;
428ae771770SStanislav Sedov else {
429ae771770SStanislav Sedov for (i = 0; i < ds1len; i++) {
430ae771770SStanislav Sedov *diff = ds1lp[i] - ds2lp[i];
431ae771770SStanislav Sedov if (*diff)
432ae771770SStanislav Sedov break;
433ae771770SStanislav Sedov }
434ae771770SStanislav Sedov }
435ae771770SStanislav Sedov free(ds1lp);
436ae771770SStanislav Sedov free(ds2lp);
437ae771770SStanislav Sedov
438ae771770SStanislav Sedov return 0;
439ae771770SStanislav Sedov }
440ae771770SStanislav Sedov
441ae771770SStanislav Sedov int
_hx509_name_cmp(const Name * n1,const Name * n2,int * c)442ae771770SStanislav Sedov _hx509_name_cmp(const Name *n1, const Name *n2, int *c)
443ae771770SStanislav Sedov {
444ae771770SStanislav Sedov int ret;
445ae771770SStanislav Sedov size_t i, j;
446ae771770SStanislav Sedov
447ae771770SStanislav Sedov *c = n1->u.rdnSequence.len - n2->u.rdnSequence.len;
448ae771770SStanislav Sedov if (*c)
449ae771770SStanislav Sedov return 0;
450c19800e8SDoug Rabson
451c19800e8SDoug Rabson for (i = 0 ; i < n1->u.rdnSequence.len; i++) {
452ae771770SStanislav Sedov *c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len;
453ae771770SStanislav Sedov if (*c)
454ae771770SStanislav Sedov return 0;
455c19800e8SDoug Rabson
456c19800e8SDoug Rabson for (j = 0; j < n1->u.rdnSequence.val[i].len; j++) {
457ae771770SStanislav Sedov *c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type,
458c19800e8SDoug Rabson &n1->u.rdnSequence.val[i].val[j].type);
459ae771770SStanislav Sedov if (*c)
460ae771770SStanislav Sedov return 0;
461c19800e8SDoug Rabson
462ae771770SStanislav Sedov ret = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value,
463ae771770SStanislav Sedov &n2->u.rdnSequence.val[i].val[j].value,
464ae771770SStanislav Sedov c);
465ae771770SStanislav Sedov if (ret)
466ae771770SStanislav Sedov return ret;
467ae771770SStanislav Sedov if (*c)
468ae771770SStanislav Sedov return 0;
469c19800e8SDoug Rabson }
470c19800e8SDoug Rabson }
471ae771770SStanislav Sedov *c = 0;
472c19800e8SDoug Rabson return 0;
473c19800e8SDoug Rabson }
474c19800e8SDoug Rabson
475c19800e8SDoug Rabson /**
476c19800e8SDoug Rabson * Compare to hx509 name object, useful for sorting.
477c19800e8SDoug Rabson *
478c19800e8SDoug Rabson * @param n1 a hx509 name object.
479c19800e8SDoug Rabson * @param n2 a hx509 name object.
480c19800e8SDoug Rabson *
481c19800e8SDoug Rabson * @return 0 the objects are the same, returns > 0 is n2 is "larger"
482c19800e8SDoug Rabson * then n2, < 0 if n1 is "smaller" then n2.
483c19800e8SDoug Rabson *
484c19800e8SDoug Rabson * @ingroup hx509_name
485c19800e8SDoug Rabson */
486c19800e8SDoug Rabson
487c19800e8SDoug Rabson int
hx509_name_cmp(hx509_name n1,hx509_name n2)488c19800e8SDoug Rabson hx509_name_cmp(hx509_name n1, hx509_name n2)
489c19800e8SDoug Rabson {
490ae771770SStanislav Sedov int ret, diff;
491ae771770SStanislav Sedov ret = _hx509_name_cmp(&n1->der_name, &n2->der_name, &diff);
492ae771770SStanislav Sedov if (ret)
493ae771770SStanislav Sedov return ret;
494ae771770SStanislav Sedov return diff;
495c19800e8SDoug Rabson }
496c19800e8SDoug Rabson
497c19800e8SDoug Rabson
498c19800e8SDoug Rabson int
_hx509_name_from_Name(const Name * n,hx509_name * name)499c19800e8SDoug Rabson _hx509_name_from_Name(const Name *n, hx509_name *name)
500c19800e8SDoug Rabson {
501c19800e8SDoug Rabson int ret;
502c19800e8SDoug Rabson *name = calloc(1, sizeof(**name));
503c19800e8SDoug Rabson if (*name == NULL)
504c19800e8SDoug Rabson return ENOMEM;
505c19800e8SDoug Rabson ret = copy_Name(n, &(*name)->der_name);
506c19800e8SDoug Rabson if (ret) {
507c19800e8SDoug Rabson free(*name);
508c19800e8SDoug Rabson *name = NULL;
509c19800e8SDoug Rabson }
510c19800e8SDoug Rabson return ret;
511c19800e8SDoug Rabson }
512c19800e8SDoug Rabson
513c19800e8SDoug Rabson int
_hx509_name_modify(hx509_context context,Name * name,int append,const heim_oid * oid,const char * str)514c19800e8SDoug Rabson _hx509_name_modify(hx509_context context,
515c19800e8SDoug Rabson Name *name,
516c19800e8SDoug Rabson int append,
517c19800e8SDoug Rabson const heim_oid *oid,
518c19800e8SDoug Rabson const char *str)
519c19800e8SDoug Rabson {
520c19800e8SDoug Rabson RelativeDistinguishedName *rdn;
521c19800e8SDoug Rabson int ret;
522c19800e8SDoug Rabson void *ptr;
523c19800e8SDoug Rabson
524c19800e8SDoug Rabson ptr = realloc(name->u.rdnSequence.val,
525c19800e8SDoug Rabson sizeof(name->u.rdnSequence.val[0]) *
526c19800e8SDoug Rabson (name->u.rdnSequence.len + 1));
527c19800e8SDoug Rabson if (ptr == NULL) {
528c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
529c19800e8SDoug Rabson return ENOMEM;
530c19800e8SDoug Rabson }
531c19800e8SDoug Rabson name->u.rdnSequence.val = ptr;
532c19800e8SDoug Rabson
533c19800e8SDoug Rabson if (append) {
534c19800e8SDoug Rabson rdn = &name->u.rdnSequence.val[name->u.rdnSequence.len];
535c19800e8SDoug Rabson } else {
536c19800e8SDoug Rabson memmove(&name->u.rdnSequence.val[1],
537c19800e8SDoug Rabson &name->u.rdnSequence.val[0],
538c19800e8SDoug Rabson name->u.rdnSequence.len *
539c19800e8SDoug Rabson sizeof(name->u.rdnSequence.val[0]));
540c19800e8SDoug Rabson
541c19800e8SDoug Rabson rdn = &name->u.rdnSequence.val[0];
542c19800e8SDoug Rabson }
543c19800e8SDoug Rabson rdn->val = malloc(sizeof(rdn->val[0]));
544c19800e8SDoug Rabson if (rdn->val == NULL)
545c19800e8SDoug Rabson return ENOMEM;
546c19800e8SDoug Rabson rdn->len = 1;
547c19800e8SDoug Rabson ret = der_copy_oid(oid, &rdn->val[0].type);
548c19800e8SDoug Rabson if (ret)
549c19800e8SDoug Rabson return ret;
550c19800e8SDoug Rabson rdn->val[0].value.element = choice_DirectoryString_utf8String;
551c19800e8SDoug Rabson rdn->val[0].value.u.utf8String = strdup(str);
552c19800e8SDoug Rabson if (rdn->val[0].value.u.utf8String == NULL)
553c19800e8SDoug Rabson return ENOMEM;
554c19800e8SDoug Rabson name->u.rdnSequence.len += 1;
555c19800e8SDoug Rabson
556c19800e8SDoug Rabson return 0;
557c19800e8SDoug Rabson }
558c19800e8SDoug Rabson
559c19800e8SDoug Rabson /**
560c19800e8SDoug Rabson * Parse a string into a hx509 name object.
561c19800e8SDoug Rabson *
562c19800e8SDoug Rabson * @param context A hx509 context.
563c19800e8SDoug Rabson * @param str a string to parse.
564c19800e8SDoug Rabson * @param name the resulting object, NULL in case of error.
565c19800e8SDoug Rabson *
566c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
567c19800e8SDoug Rabson *
568c19800e8SDoug Rabson * @ingroup hx509_name
569c19800e8SDoug Rabson */
570c19800e8SDoug Rabson
571c19800e8SDoug Rabson int
hx509_parse_name(hx509_context context,const char * str,hx509_name * name)572c19800e8SDoug Rabson hx509_parse_name(hx509_context context, const char *str, hx509_name *name)
573c19800e8SDoug Rabson {
574c19800e8SDoug Rabson const char *p, *q;
575c19800e8SDoug Rabson size_t len;
576c19800e8SDoug Rabson hx509_name n;
577c19800e8SDoug Rabson int ret;
578c19800e8SDoug Rabson
579c19800e8SDoug Rabson *name = NULL;
580c19800e8SDoug Rabson
581c19800e8SDoug Rabson n = calloc(1, sizeof(*n));
582c19800e8SDoug Rabson if (n == NULL) {
583c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
584c19800e8SDoug Rabson return ENOMEM;
585c19800e8SDoug Rabson }
586c19800e8SDoug Rabson
587c19800e8SDoug Rabson n->der_name.element = choice_Name_rdnSequence;
588c19800e8SDoug Rabson
589c19800e8SDoug Rabson p = str;
590c19800e8SDoug Rabson
591c19800e8SDoug Rabson while (p != NULL && *p != '\0') {
592c19800e8SDoug Rabson heim_oid oid;
593c19800e8SDoug Rabson int last;
594c19800e8SDoug Rabson
595c19800e8SDoug Rabson q = strchr(p, ',');
596c19800e8SDoug Rabson if (q) {
597c19800e8SDoug Rabson len = (q - p);
598c19800e8SDoug Rabson last = 1;
599c19800e8SDoug Rabson } else {
600c19800e8SDoug Rabson len = strlen(p);
601c19800e8SDoug Rabson last = 0;
602c19800e8SDoug Rabson }
603c19800e8SDoug Rabson
604c19800e8SDoug Rabson q = strchr(p, '=');
605c19800e8SDoug Rabson if (q == NULL) {
606c19800e8SDoug Rabson ret = HX509_PARSING_NAME_FAILED;
607c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, "missing = in %s", p);
608c19800e8SDoug Rabson goto out;
609c19800e8SDoug Rabson }
610c19800e8SDoug Rabson if (q == p) {
611c19800e8SDoug Rabson ret = HX509_PARSING_NAME_FAILED;
612c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret,
613c19800e8SDoug Rabson "missing name before = in %s", p);
614c19800e8SDoug Rabson goto out;
615c19800e8SDoug Rabson }
616c19800e8SDoug Rabson
617ae771770SStanislav Sedov if ((size_t)(q - p) > len) {
618c19800e8SDoug Rabson ret = HX509_PARSING_NAME_FAILED;
619c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, " = after , in %s", p);
620c19800e8SDoug Rabson goto out;
621c19800e8SDoug Rabson }
622c19800e8SDoug Rabson
623c19800e8SDoug Rabson ret = stringtooid(p, q - p, &oid);
624c19800e8SDoug Rabson if (ret) {
625c19800e8SDoug Rabson ret = HX509_PARSING_NAME_FAILED;
626c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret,
627c19800e8SDoug Rabson "unknown type: %.*s", (int)(q - p), p);
628c19800e8SDoug Rabson goto out;
629c19800e8SDoug Rabson }
630c19800e8SDoug Rabson
631c19800e8SDoug Rabson {
632c19800e8SDoug Rabson size_t pstr_len = len - (q - p) - 1;
633c19800e8SDoug Rabson const char *pstr = p + (q - p) + 1;
634c19800e8SDoug Rabson char *r;
635c19800e8SDoug Rabson
636c19800e8SDoug Rabson r = malloc(pstr_len + 1);
637c19800e8SDoug Rabson if (r == NULL) {
638c19800e8SDoug Rabson der_free_oid(&oid);
639c19800e8SDoug Rabson ret = ENOMEM;
640c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, "out of memory");
641c19800e8SDoug Rabson goto out;
642c19800e8SDoug Rabson }
643c19800e8SDoug Rabson memcpy(r, pstr, pstr_len);
644c19800e8SDoug Rabson r[pstr_len] = '\0';
645c19800e8SDoug Rabson
646c19800e8SDoug Rabson ret = _hx509_name_modify(context, &n->der_name, 0, &oid, r);
647c19800e8SDoug Rabson free(r);
648c19800e8SDoug Rabson der_free_oid(&oid);
649c19800e8SDoug Rabson if(ret)
650c19800e8SDoug Rabson goto out;
651c19800e8SDoug Rabson }
652c19800e8SDoug Rabson p += len + last;
653c19800e8SDoug Rabson }
654c19800e8SDoug Rabson
655c19800e8SDoug Rabson *name = n;
656c19800e8SDoug Rabson
657c19800e8SDoug Rabson return 0;
658c19800e8SDoug Rabson out:
659c19800e8SDoug Rabson hx509_name_free(&n);
660c19800e8SDoug Rabson return HX509_NAME_MALFORMED;
661c19800e8SDoug Rabson }
662c19800e8SDoug Rabson
663c19800e8SDoug Rabson /**
664c19800e8SDoug Rabson * Copy a hx509 name object.
665c19800e8SDoug Rabson *
666c19800e8SDoug Rabson * @param context A hx509 cotext.
667c19800e8SDoug Rabson * @param from the name to copy from
668c19800e8SDoug Rabson * @param to the name to copy to
669c19800e8SDoug Rabson *
670c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
671c19800e8SDoug Rabson *
672c19800e8SDoug Rabson * @ingroup hx509_name
673c19800e8SDoug Rabson */
674c19800e8SDoug Rabson
675c19800e8SDoug Rabson int
hx509_name_copy(hx509_context context,const hx509_name from,hx509_name * to)676c19800e8SDoug Rabson hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to)
677c19800e8SDoug Rabson {
678c19800e8SDoug Rabson int ret;
679c19800e8SDoug Rabson
680c19800e8SDoug Rabson *to = calloc(1, sizeof(**to));
681c19800e8SDoug Rabson if (*to == NULL)
682c19800e8SDoug Rabson return ENOMEM;
683c19800e8SDoug Rabson ret = copy_Name(&from->der_name, &(*to)->der_name);
684c19800e8SDoug Rabson if (ret) {
685c19800e8SDoug Rabson free(*to);
686c19800e8SDoug Rabson *to = NULL;
687c19800e8SDoug Rabson return ENOMEM;
688c19800e8SDoug Rabson }
689c19800e8SDoug Rabson return 0;
690c19800e8SDoug Rabson }
691c19800e8SDoug Rabson
692c19800e8SDoug Rabson /**
693c19800e8SDoug Rabson * Convert a hx509_name into a Name.
694c19800e8SDoug Rabson *
695c19800e8SDoug Rabson * @param from the name to copy from
696c19800e8SDoug Rabson * @param to the name to copy to
697c19800e8SDoug Rabson *
698c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
699c19800e8SDoug Rabson *
700c19800e8SDoug Rabson * @ingroup hx509_name
701c19800e8SDoug Rabson */
702c19800e8SDoug Rabson
703c19800e8SDoug Rabson int
hx509_name_to_Name(const hx509_name from,Name * to)704c19800e8SDoug Rabson hx509_name_to_Name(const hx509_name from, Name *to)
705c19800e8SDoug Rabson {
706c19800e8SDoug Rabson return copy_Name(&from->der_name, to);
707c19800e8SDoug Rabson }
708c19800e8SDoug Rabson
709c19800e8SDoug Rabson int
hx509_name_normalize(hx509_context context,hx509_name name)710c19800e8SDoug Rabson hx509_name_normalize(hx509_context context, hx509_name name)
711c19800e8SDoug Rabson {
712c19800e8SDoug Rabson return 0;
713c19800e8SDoug Rabson }
714c19800e8SDoug Rabson
715c19800e8SDoug Rabson /**
716c19800e8SDoug Rabson * Expands variables in the name using env. Variables are on the form
717c19800e8SDoug Rabson * ${name}. Useful when dealing with certificate templates.
718c19800e8SDoug Rabson *
719c19800e8SDoug Rabson * @param context A hx509 cotext.
720c19800e8SDoug Rabson * @param name the name to expand.
721c19800e8SDoug Rabson * @param env environment variable to expand.
722c19800e8SDoug Rabson *
723c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
724c19800e8SDoug Rabson *
725c19800e8SDoug Rabson * @ingroup hx509_name
726c19800e8SDoug Rabson */
727c19800e8SDoug Rabson
728c19800e8SDoug Rabson int
hx509_name_expand(hx509_context context,hx509_name name,hx509_env env)729c19800e8SDoug Rabson hx509_name_expand(hx509_context context,
730c19800e8SDoug Rabson hx509_name name,
731c19800e8SDoug Rabson hx509_env env)
732c19800e8SDoug Rabson {
733c19800e8SDoug Rabson Name *n = &name->der_name;
734ae771770SStanislav Sedov size_t i, j;
735c19800e8SDoug Rabson
736c19800e8SDoug Rabson if (env == NULL)
737c19800e8SDoug Rabson return 0;
738c19800e8SDoug Rabson
739c19800e8SDoug Rabson if (n->element != choice_Name_rdnSequence) {
740c19800e8SDoug Rabson hx509_set_error_string(context, 0, EINVAL, "RDN not of supported type");
741c19800e8SDoug Rabson return EINVAL;
742c19800e8SDoug Rabson }
743c19800e8SDoug Rabson
744c19800e8SDoug Rabson for (i = 0 ; i < n->u.rdnSequence.len; i++) {
745c19800e8SDoug Rabson for (j = 0; j < n->u.rdnSequence.val[i].len; j++) {
746c19800e8SDoug Rabson /** Only UTF8String rdnSequence names are allowed */
747c19800e8SDoug Rabson /*
748c19800e8SDoug Rabson THIS SHOULD REALLY BE:
749c19800e8SDoug Rabson COMP = n->u.rdnSequence.val[i].val[j];
750c19800e8SDoug Rabson normalize COMP to utf8
751c19800e8SDoug Rabson check if there are variables
752c19800e8SDoug Rabson expand variables
753c19800e8SDoug Rabson convert back to orignal format, store in COMP
754c19800e8SDoug Rabson free normalized utf8 string
755c19800e8SDoug Rabson */
756c19800e8SDoug Rabson DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value;
757c19800e8SDoug Rabson char *p, *p2;
758c19800e8SDoug Rabson struct rk_strpool *strpool = NULL;
759c19800e8SDoug Rabson
760c19800e8SDoug Rabson if (ds->element != choice_DirectoryString_utf8String) {
761c19800e8SDoug Rabson hx509_set_error_string(context, 0, EINVAL, "unsupported type");
762c19800e8SDoug Rabson return EINVAL;
763c19800e8SDoug Rabson }
764c19800e8SDoug Rabson p = strstr(ds->u.utf8String, "${");
765c19800e8SDoug Rabson if (p) {
766c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "%.*s",
767c19800e8SDoug Rabson (int)(p - ds->u.utf8String),
768c19800e8SDoug Rabson ds->u.utf8String);
769c19800e8SDoug Rabson if (strpool == NULL) {
770c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
771c19800e8SDoug Rabson return ENOMEM;
772c19800e8SDoug Rabson }
773c19800e8SDoug Rabson }
774c19800e8SDoug Rabson while (p != NULL) {
775c19800e8SDoug Rabson /* expand variables */
776c19800e8SDoug Rabson const char *value;
777c19800e8SDoug Rabson p2 = strchr(p, '}');
778c19800e8SDoug Rabson if (p2 == NULL) {
779c19800e8SDoug Rabson hx509_set_error_string(context, 0, EINVAL, "missing }");
780c19800e8SDoug Rabson rk_strpoolfree(strpool);
781c19800e8SDoug Rabson return EINVAL;
782c19800e8SDoug Rabson }
783c19800e8SDoug Rabson p += 2;
784c19800e8SDoug Rabson value = hx509_env_lfind(context, env, p, p2 - p);
785c19800e8SDoug Rabson if (value == NULL) {
786c19800e8SDoug Rabson hx509_set_error_string(context, 0, EINVAL,
787c19800e8SDoug Rabson "variable %.*s missing",
788c19800e8SDoug Rabson (int)(p2 - p), p);
789c19800e8SDoug Rabson rk_strpoolfree(strpool);
790c19800e8SDoug Rabson return EINVAL;
791c19800e8SDoug Rabson }
792c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "%s", value);
793c19800e8SDoug Rabson if (strpool == NULL) {
794c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
795c19800e8SDoug Rabson return ENOMEM;
796c19800e8SDoug Rabson }
797c19800e8SDoug Rabson p2++;
798c19800e8SDoug Rabson
799c19800e8SDoug Rabson p = strstr(p2, "${");
800c19800e8SDoug Rabson if (p)
801c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "%.*s",
802c19800e8SDoug Rabson (int)(p - p2), p2);
803c19800e8SDoug Rabson else
804c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "%s", p2);
805c19800e8SDoug Rabson if (strpool == NULL) {
806c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
807c19800e8SDoug Rabson return ENOMEM;
808c19800e8SDoug Rabson }
809c19800e8SDoug Rabson }
810c19800e8SDoug Rabson if (strpool) {
811c19800e8SDoug Rabson free(ds->u.utf8String);
812c19800e8SDoug Rabson ds->u.utf8String = rk_strpoolcollect(strpool);
813c19800e8SDoug Rabson if (ds->u.utf8String == NULL) {
814c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
815c19800e8SDoug Rabson return ENOMEM;
816c19800e8SDoug Rabson }
817c19800e8SDoug Rabson }
818c19800e8SDoug Rabson }
819c19800e8SDoug Rabson }
820c19800e8SDoug Rabson return 0;
821c19800e8SDoug Rabson }
822c19800e8SDoug Rabson
823c19800e8SDoug Rabson /**
824c19800e8SDoug Rabson * Free a hx509 name object, upond return *name will be NULL.
825c19800e8SDoug Rabson *
826c19800e8SDoug Rabson * @param name a hx509 name object to be freed.
827c19800e8SDoug Rabson *
828c19800e8SDoug Rabson * @ingroup hx509_name
829c19800e8SDoug Rabson */
830c19800e8SDoug Rabson
831c19800e8SDoug Rabson void
hx509_name_free(hx509_name * name)832c19800e8SDoug Rabson hx509_name_free(hx509_name *name)
833c19800e8SDoug Rabson {
834c19800e8SDoug Rabson free_Name(&(*name)->der_name);
835c19800e8SDoug Rabson memset(*name, 0, sizeof(**name));
836c19800e8SDoug Rabson free(*name);
837c19800e8SDoug Rabson *name = NULL;
838c19800e8SDoug Rabson }
839c19800e8SDoug Rabson
840c19800e8SDoug Rabson /**
841c19800e8SDoug Rabson * Convert a DER encoded name info a string.
842c19800e8SDoug Rabson *
843c19800e8SDoug Rabson * @param data data to a DER/BER encoded name
844c19800e8SDoug Rabson * @param length length of data
845c19800e8SDoug Rabson * @param str the resulting string, is NULL on failure.
846c19800e8SDoug Rabson *
847c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
848c19800e8SDoug Rabson *
849c19800e8SDoug Rabson * @ingroup hx509_name
850c19800e8SDoug Rabson */
851c19800e8SDoug Rabson
852c19800e8SDoug Rabson int
hx509_unparse_der_name(const void * data,size_t length,char ** str)853c19800e8SDoug Rabson hx509_unparse_der_name(const void *data, size_t length, char **str)
854c19800e8SDoug Rabson {
855c19800e8SDoug Rabson Name name;
856c19800e8SDoug Rabson int ret;
857c19800e8SDoug Rabson
858c19800e8SDoug Rabson *str = NULL;
859c19800e8SDoug Rabson
860c19800e8SDoug Rabson ret = decode_Name(data, length, &name, NULL);
861c19800e8SDoug Rabson if (ret)
862c19800e8SDoug Rabson return ret;
863c19800e8SDoug Rabson ret = _hx509_Name_to_string(&name, str);
864c19800e8SDoug Rabson free_Name(&name);
865c19800e8SDoug Rabson return ret;
866c19800e8SDoug Rabson }
867c19800e8SDoug Rabson
868c19800e8SDoug Rabson /**
869c19800e8SDoug Rabson * Convert a hx509_name object to DER encoded name.
870c19800e8SDoug Rabson *
871c19800e8SDoug Rabson * @param name name to concert
872c19800e8SDoug Rabson * @param os data to a DER encoded name, free the resulting octet
873c19800e8SDoug Rabson * string with hx509_xfree(os->data).
874c19800e8SDoug Rabson *
875c19800e8SDoug Rabson * @return An hx509 error code, see hx509_get_error_string().
876c19800e8SDoug Rabson *
877c19800e8SDoug Rabson * @ingroup hx509_name
878c19800e8SDoug Rabson */
879c19800e8SDoug Rabson
880c19800e8SDoug Rabson int
hx509_name_binary(const hx509_name name,heim_octet_string * os)881c19800e8SDoug Rabson hx509_name_binary(const hx509_name name, heim_octet_string *os)
882c19800e8SDoug Rabson {
883c19800e8SDoug Rabson size_t size;
884c19800e8SDoug Rabson int ret;
885c19800e8SDoug Rabson
886c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(Name, os->data, os->length, &name->der_name, &size, ret);
887c19800e8SDoug Rabson if (ret)
888c19800e8SDoug Rabson return ret;
889c19800e8SDoug Rabson if (os->length != size)
890c19800e8SDoug Rabson _hx509_abort("internal ASN.1 encoder error");
891c19800e8SDoug Rabson
892c19800e8SDoug Rabson return 0;
893c19800e8SDoug Rabson }
894c19800e8SDoug Rabson
895c19800e8SDoug Rabson int
_hx509_unparse_Name(const Name * aname,char ** str)896c19800e8SDoug Rabson _hx509_unparse_Name(const Name *aname, char **str)
897c19800e8SDoug Rabson {
898c19800e8SDoug Rabson hx509_name name;
899c19800e8SDoug Rabson int ret;
900c19800e8SDoug Rabson
901c19800e8SDoug Rabson ret = _hx509_name_from_Name(aname, &name);
902c19800e8SDoug Rabson if (ret)
903c19800e8SDoug Rabson return ret;
904c19800e8SDoug Rabson
905c19800e8SDoug Rabson ret = hx509_name_to_string(name, str);
906c19800e8SDoug Rabson hx509_name_free(&name);
907c19800e8SDoug Rabson return ret;
908c19800e8SDoug Rabson }
909c19800e8SDoug Rabson
910c19800e8SDoug Rabson /**
911c19800e8SDoug Rabson * Unparse the hx509 name in name into a string.
912c19800e8SDoug Rabson *
913c19800e8SDoug Rabson * @param name the name to check if its empty/null.
914c19800e8SDoug Rabson *
915c19800e8SDoug Rabson * @return non zero if the name is empty/null.
916c19800e8SDoug Rabson *
917c19800e8SDoug Rabson * @ingroup hx509_name
918c19800e8SDoug Rabson */
919c19800e8SDoug Rabson
920c19800e8SDoug Rabson int
hx509_name_is_null_p(const hx509_name name)921c19800e8SDoug Rabson hx509_name_is_null_p(const hx509_name name)
922c19800e8SDoug Rabson {
923c19800e8SDoug Rabson return name->der_name.u.rdnSequence.len == 0;
924c19800e8SDoug Rabson }
925c19800e8SDoug Rabson
926c19800e8SDoug Rabson /**
927c19800e8SDoug Rabson * Unparse the hx509 name in name into a string.
928c19800e8SDoug Rabson *
929c19800e8SDoug Rabson * @param name the name to print
930c19800e8SDoug Rabson * @param str an allocated string returns the name in string form
931c19800e8SDoug Rabson *
932ae771770SStanislav Sedov * @return An hx509 error code, see hx509_get_error_string().
933c19800e8SDoug Rabson *
934c19800e8SDoug Rabson * @ingroup hx509_name
935c19800e8SDoug Rabson */
936c19800e8SDoug Rabson
937c19800e8SDoug Rabson int
hx509_general_name_unparse(GeneralName * name,char ** str)938c19800e8SDoug Rabson hx509_general_name_unparse(GeneralName *name, char **str)
939c19800e8SDoug Rabson {
940c19800e8SDoug Rabson struct rk_strpool *strpool = NULL;
941*ed549cb0SCy Schubert int ret = 0;
942c19800e8SDoug Rabson
943c19800e8SDoug Rabson *str = NULL;
944c19800e8SDoug Rabson
945c19800e8SDoug Rabson switch (name->element) {
946c19800e8SDoug Rabson case choice_GeneralName_otherName: {
947ae771770SStanislav Sedov char *oid;
948ae771770SStanislav Sedov hx509_oid_sprint(&name->u.otherName.type_id, &oid);
949ae771770SStanislav Sedov if (oid == NULL)
950c19800e8SDoug Rabson return ENOMEM;
951ae771770SStanislav Sedov strpool = rk_strpoolprintf(strpool, "otherName: %s", oid);
952ae771770SStanislav Sedov free(oid);
953c19800e8SDoug Rabson break;
954c19800e8SDoug Rabson }
955c19800e8SDoug Rabson case choice_GeneralName_rfc822Name:
956ae771770SStanislav Sedov strpool = rk_strpoolprintf(strpool, "rfc822Name: %.*s\n",
957ae771770SStanislav Sedov (int)name->u.rfc822Name.length,
958ae771770SStanislav Sedov (char *)name->u.rfc822Name.data);
959c19800e8SDoug Rabson break;
960c19800e8SDoug Rabson case choice_GeneralName_dNSName:
961ae771770SStanislav Sedov strpool = rk_strpoolprintf(strpool, "dNSName: %.*s\n",
962ae771770SStanislav Sedov (int)name->u.dNSName.length,
963ae771770SStanislav Sedov (char *)name->u.dNSName.data);
964c19800e8SDoug Rabson break;
965c19800e8SDoug Rabson case choice_GeneralName_directoryName: {
966c19800e8SDoug Rabson Name dir;
967c19800e8SDoug Rabson char *s;
968c19800e8SDoug Rabson memset(&dir, 0, sizeof(dir));
969c19800e8SDoug Rabson dir.element = name->u.directoryName.element;
970c19800e8SDoug Rabson dir.u.rdnSequence = name->u.directoryName.u.rdnSequence;
971c19800e8SDoug Rabson ret = _hx509_unparse_Name(&dir, &s);
972c19800e8SDoug Rabson if (ret)
973c19800e8SDoug Rabson return ret;
974c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "directoryName: %s", s);
975c19800e8SDoug Rabson free(s);
976c19800e8SDoug Rabson break;
977c19800e8SDoug Rabson }
978c19800e8SDoug Rabson case choice_GeneralName_uniformResourceIdentifier:
979ae771770SStanislav Sedov strpool = rk_strpoolprintf(strpool, "URI: %.*s",
980ae771770SStanislav Sedov (int)name->u.uniformResourceIdentifier.length,
981ae771770SStanislav Sedov (char *)name->u.uniformResourceIdentifier.data);
982c19800e8SDoug Rabson break;
983c19800e8SDoug Rabson case choice_GeneralName_iPAddress: {
984c19800e8SDoug Rabson unsigned char *a = name->u.iPAddress.data;
985c19800e8SDoug Rabson
986c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "IPAddress: ");
987c19800e8SDoug Rabson if (strpool == NULL)
988c19800e8SDoug Rabson break;
989c19800e8SDoug Rabson if (name->u.iPAddress.length == 4)
990c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool, "%d.%d.%d.%d",
991c19800e8SDoug Rabson a[0], a[1], a[2], a[3]);
992c19800e8SDoug Rabson else if (name->u.iPAddress.length == 16)
993c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool,
994c19800e8SDoug Rabson "%02X:%02X:%02X:%02X:"
995c19800e8SDoug Rabson "%02X:%02X:%02X:%02X:"
996c19800e8SDoug Rabson "%02X:%02X:%02X:%02X:"
997c19800e8SDoug Rabson "%02X:%02X:%02X:%02X",
998c19800e8SDoug Rabson a[0], a[1], a[2], a[3],
999c19800e8SDoug Rabson a[4], a[5], a[6], a[7],
1000c19800e8SDoug Rabson a[8], a[9], a[10], a[11],
1001c19800e8SDoug Rabson a[12], a[13], a[14], a[15]);
1002c19800e8SDoug Rabson else
1003c19800e8SDoug Rabson strpool = rk_strpoolprintf(strpool,
1004c19800e8SDoug Rabson "unknown IP address of length %lu",
1005c19800e8SDoug Rabson (unsigned long)name->u.iPAddress.length);
1006c19800e8SDoug Rabson break;
1007c19800e8SDoug Rabson }
1008c19800e8SDoug Rabson case choice_GeneralName_registeredID: {
1009ae771770SStanislav Sedov char *oid;
1010ae771770SStanislav Sedov hx509_oid_sprint(&name->u.registeredID, &oid);
1011ae771770SStanislav Sedov if (oid == NULL)
1012c19800e8SDoug Rabson return ENOMEM;
1013ae771770SStanislav Sedov strpool = rk_strpoolprintf(strpool, "registeredID: %s", oid);
1014ae771770SStanislav Sedov free(oid);
1015c19800e8SDoug Rabson break;
1016c19800e8SDoug Rabson }
1017c19800e8SDoug Rabson default:
1018c19800e8SDoug Rabson return EINVAL;
1019c19800e8SDoug Rabson }
1020*ed549cb0SCy Schubert if (ret)
1021*ed549cb0SCy Schubert rk_strpoolfree(strpool);
1022*ed549cb0SCy Schubert else if (strpool == NULL || (*str = rk_strpoolcollect(strpool)) == NULL)
1023c19800e8SDoug Rabson return ENOMEM;
1024*ed549cb0SCy Schubert return ret;
1025c19800e8SDoug Rabson }
1026