LDAP string escaping was made stricter (rfc4514 conforming)
[gnutls.git] / lib / x509 / dn.c
blob1bee85523b5c43ade6694b6ea47bf05e87be19ae
1 /*
2 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <libtasn1.h>
25 #include <gnutls_datum.h>
26 #include <gnutls_global.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_str.h>
29 #include <common.h>
30 #include <gnutls_num.h>
32 /* This file includes all the required to parse an X.509 Distriguished
33 * Name (you need a parser just to read a name in the X.509 protoocols!!!)
36 /* Escapes a string following the rules from RFC4514.
38 static int
39 str_escape (const gnutls_datum_t* str, gnutls_datum_t * escaped)
41 unsigned int j, i;
42 uint8_t *buffer = NULL;
43 int ret;
45 if (str == NULL)
46 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
48 /* the string will be at most twice the original */
49 buffer = gnutls_malloc(str->size*2+2);
50 if (buffer == NULL)
51 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
53 for (i = j = 0; i < str->size; i++)
55 if (str->data[i] == 0)
57 /* this is handled earlier */
58 ret = gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR);
59 goto cleanup;
62 if (str->data[i] == ',' || str->data[i] == '+' || str->data[i] == '"'
63 || str->data[i] == '\\' || str->data[i] == '<' || str->data[i] == '>'
64 || str->data[i] == ';' || str->data[i] == 0)
65 buffer[j++] = '\\';
66 else if (i==0 && str->data[i] == '#')
67 buffer[j++] = '\\';
68 else if (i==0 && str->data[i] == ' ')
69 buffer[j++] = '\\';
70 else if (i==(str->size-1) && str->data[i] == ' ')
71 buffer[j++] = '\\';
73 buffer[j++] = str->data[i];
76 /* null terminate the string */
77 buffer[j] = 0;
78 escaped->data = buffer;
79 escaped->size = j;
81 return 0;
82 cleanup:
83 gnutls_free(buffer);
84 return ret;
87 /* Parses an X509 DN in the asn1_struct, and puts the output into
88 * the string buf. The output is an LDAP encoded DN.
90 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
91 * That is to point in the rndSequence.
93 int
94 _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
95 const char *asn1_rdn_name, char *buf,
96 size_t * sizeof_buf)
98 gnutls_buffer_st out_str;
99 int k2, k1, result;
100 char tmpbuffer1[ASN1_MAX_NAME_SIZE];
101 char tmpbuffer2[ASN1_MAX_NAME_SIZE];
102 char tmpbuffer3[ASN1_MAX_NAME_SIZE];
103 uint8_t value[MAX_STRING_LEN], *value2 = NULL;
104 gnutls_datum_t td, escaped = {NULL, 0};
105 const char *ldap_desc;
106 char oid[MAX_OID_SIZE];
107 int len;
109 if (sizeof_buf == NULL)
111 gnutls_assert ();
112 return GNUTLS_E_INVALID_REQUEST;
115 if (*sizeof_buf > 0 && buf)
116 buf[0] = 0;
117 else
118 *sizeof_buf = 0;
120 _gnutls_buffer_init (&out_str);
122 k1 = 0;
126 k1++;
127 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
129 if (asn1_rdn_name[0] != 0)
130 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name,
131 k1);
132 else
133 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
135 len = sizeof (value) - 1;
136 result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);
138 if (result == ASN1_ELEMENT_NOT_FOUND)
140 break;
143 if (result != ASN1_VALUE_NOT_FOUND)
145 gnutls_assert ();
146 result = _gnutls_asn2err (result);
147 goto cleanup;
150 k2 = 0;
153 { /* Move to the attibute type and values
155 k2++;
157 if (tmpbuffer1[0] != 0)
158 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
159 k2);
160 else
161 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);
163 /* Try to read the RelativeDistinguishedName attributes.
166 len = sizeof (value) - 1;
167 result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);
169 if (result == ASN1_ELEMENT_NOT_FOUND)
170 break;
171 if (result != ASN1_VALUE_NOT_FOUND)
173 gnutls_assert ();
174 result = _gnutls_asn2err (result);
175 goto cleanup;
178 /* Read the OID
180 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
181 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");
183 len = sizeof (oid) - 1;
184 result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);
186 if (result == ASN1_ELEMENT_NOT_FOUND)
187 break;
188 else if (result != ASN1_SUCCESS)
190 gnutls_assert ();
191 result = _gnutls_asn2err (result);
192 goto cleanup;
195 /* Read the Value
197 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
198 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");
200 len = 0;
201 result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len);
202 if (result != ASN1_MEM_ERROR)
204 gnutls_assert ();
205 result = _gnutls_asn2err (result);
206 goto cleanup;
209 value2 = gnutls_malloc (len);
210 if (value2 == NULL)
212 gnutls_assert ();
213 result = GNUTLS_E_MEMORY_ERROR;
214 goto cleanup;
217 result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len);
219 if (result != ASN1_SUCCESS)
221 gnutls_assert ();
222 result = _gnutls_asn2err (result);
223 goto cleanup;
225 #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
226 gnutls_assert(); \
227 goto cleanup; \
229 #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \
230 gnutls_assert(); \
231 goto cleanup; \
233 /* The encodings of adjoining RelativeDistinguishedNames are separated
234 * by a comma character (',' ASCII 44).
237 /* Where there is a multi-valued RDN, the outputs from adjoining
238 * AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
239 * character.
241 if (k1 != 1)
242 { /* the first time do not append a comma */
243 if (k2 != 1)
244 { /* adjoining multi-value RDN */
245 STR_APPEND ("+");
247 else
249 STR_APPEND (",");
253 ldap_desc = gnutls_x509_dn_oid_name (oid, GNUTLS_X509_DN_OID_RETURN_OID);
256 STR_APPEND (ldap_desc);
257 STR_APPEND ("=");
259 result =
260 _gnutls_x509_dn_to_string (oid, value2, len, &td);
261 if (result < 0)
263 gnutls_assert ();
264 _gnutls_debug_log
265 ("Cannot parse OID: '%s' with value '%s'\n",
266 oid, _gnutls_bin2hex (value2, len, tmpbuffer3, sizeof(tmpbuffer3),
267 NULL));
268 goto cleanup;
271 result = str_escape(&td, &escaped);
272 if (result < 0)
274 gnutls_assert();
275 goto cleanup;
278 DATA_APPEND (escaped.data, escaped.size);
279 _gnutls_free_datum (&td);
280 _gnutls_free_datum (&escaped);
281 gnutls_free (value2);
282 value2 = NULL;
285 while (1);
288 while (1);
290 if (out_str.length >= (unsigned int) *sizeof_buf)
292 gnutls_assert ();
293 *sizeof_buf = out_str.length + 1;
294 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
295 goto cleanup;
298 if (buf)
300 _gnutls_buffer_pop_data (&out_str, buf, sizeof_buf);
301 buf[*sizeof_buf] = 0;
303 else
304 *sizeof_buf = out_str.length;
306 result = 0;
308 cleanup:
309 gnutls_free (value2);
310 _gnutls_free_datum (&escaped);
311 _gnutls_buffer_clear (&out_str);
312 return result;
315 /* Parses an X509 DN in the asn1_struct, and searches for the
316 * given OID in the DN.
318 * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable)
319 * Otherwise the raw DER data are returned.
321 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
322 * That is to point in the rndSequence.
324 * indx specifies which OID to return. Ie 0 means return the first specified
325 * OID found, 1 the second etc.
328 _gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct,
329 const char *asn1_rdn_name,
330 const char *given_oid, int indx,
331 unsigned int raw_flag,
332 gnutls_datum_t* out)
334 int k2, k1, result;
335 char tmpbuffer1[ASN1_MAX_NAME_SIZE];
336 char tmpbuffer2[ASN1_MAX_NAME_SIZE];
337 char tmpbuffer3[ASN1_MAX_NAME_SIZE];
338 gnutls_datum_t td;
339 uint8_t value[256];
340 char oid[MAX_OID_SIZE];
341 int len;
342 int i = 0;
344 k1 = 0;
348 k1++;
349 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
351 if (asn1_rdn_name[0] != 0)
352 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name,
353 k1);
354 else
355 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
357 len = sizeof (value) - 1;
358 result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);
360 if (result == ASN1_ELEMENT_NOT_FOUND)
362 gnutls_assert ();
363 break;
366 if (result != ASN1_VALUE_NOT_FOUND)
368 gnutls_assert ();
369 result = _gnutls_asn2err (result);
370 goto cleanup;
373 k2 = 0;
376 { /* Move to the attibute type and values
378 k2++;
380 if (tmpbuffer1[0] != 0)
381 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
382 k2);
383 else
384 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);
386 /* Try to read the RelativeDistinguishedName attributes.
389 len = sizeof (value) - 1;
390 result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);
392 if (result == ASN1_ELEMENT_NOT_FOUND)
394 break;
396 if (result != ASN1_VALUE_NOT_FOUND)
398 gnutls_assert ();
399 result = _gnutls_asn2err (result);
400 goto cleanup;
403 /* Read the OID
405 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
406 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");
408 len = sizeof (oid) - 1;
409 result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);
411 if (result == ASN1_ELEMENT_NOT_FOUND)
412 break;
413 else if (result != ASN1_SUCCESS)
415 gnutls_assert ();
416 result = _gnutls_asn2err (result);
417 goto cleanup;
420 if (strcmp (oid, given_oid) == 0 && indx == i++)
421 { /* Found the OID */
423 /* Read the Value
425 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
426 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");
428 result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &td);
429 if (result < 0)
431 gnutls_assert ();
432 goto cleanup;
435 if (raw_flag != 0)
437 out->data = td.data;
438 out->size = td.size;
439 return 0;
442 else
443 { /* parse data. raw_flag == 0 */
444 result =
445 _gnutls_x509_dn_to_string (oid, td.data, td.size, out);
447 _gnutls_free_datum(&td);
448 if (result < 0)
450 gnutls_assert ();
451 goto cleanup;
454 return 0;
456 } /* raw_flag == 0 */
459 while (1);
462 while (1);
464 gnutls_assert ();
466 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
468 cleanup:
469 return result;
473 /* Parses an X509 DN in the asn1_struct, and returns the requested
474 * DN OID.
476 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
477 * That is to point in the rndSequence.
479 * indx specifies which OID to return. Ie 0 means return the first specified
480 * OID found, 1 the second etc.
483 _gnutls_x509_get_dn_oid (ASN1_TYPE asn1_struct,
484 const char *asn1_rdn_name,
485 int indx, void *_oid, size_t * sizeof_oid)
487 int k2, k1, result;
488 char tmpbuffer1[ASN1_MAX_NAME_SIZE];
489 char tmpbuffer2[ASN1_MAX_NAME_SIZE];
490 char tmpbuffer3[ASN1_MAX_NAME_SIZE];
491 char value[256];
492 char oid[MAX_OID_SIZE];
493 int len;
494 int i = 0;
496 k1 = 0;
500 k1++;
501 /* create a string like "tbsCertList.issuer.rdnSequence.?1"
503 if (asn1_rdn_name[0] != 0)
504 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name,
505 k1);
506 else
507 snprintf (tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
509 len = sizeof (value) - 1;
510 result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);
512 if (result == ASN1_ELEMENT_NOT_FOUND)
514 gnutls_assert ();
515 break;
518 if (result != ASN1_VALUE_NOT_FOUND)
520 gnutls_assert ();
521 result = _gnutls_asn2err (result);
522 goto cleanup;
525 k2 = 0;
528 { /* Move to the attibute type and values
530 k2++;
532 if (tmpbuffer1[0] != 0)
533 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1,
534 k2);
535 else
536 snprintf (tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);
538 /* Try to read the RelativeDistinguishedName attributes.
541 len = sizeof (value) - 1;
542 result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);
544 if (result == ASN1_ELEMENT_NOT_FOUND)
546 break;
548 if (result != ASN1_VALUE_NOT_FOUND)
550 gnutls_assert ();
551 result = _gnutls_asn2err (result);
552 goto cleanup;
555 /* Read the OID
557 _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
558 _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");
560 len = sizeof (oid) - 1;
561 result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);
563 if (result == ASN1_ELEMENT_NOT_FOUND)
564 break;
565 else if (result != ASN1_SUCCESS)
567 gnutls_assert ();
568 result = _gnutls_asn2err (result);
569 goto cleanup;
572 if (indx == i++)
573 { /* Found the OID */
575 len = strlen (oid) + 1;
577 if (*sizeof_oid < (unsigned) len)
579 *sizeof_oid = len;
580 gnutls_assert ();
581 return GNUTLS_E_SHORT_MEMORY_BUFFER;
584 memcpy (_oid, oid, len);
585 *sizeof_oid = len - 1;
587 return 0;
590 while (1);
593 while (1);
595 gnutls_assert ();
597 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
599 cleanup:
600 return result;
603 /* This will write the AttributeTypeAndValue field. The data must be already DER encoded.
604 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
605 * In all cases only one value is written.
607 static int
608 _gnutls_x509_write_attribute (const char *given_oid,
609 ASN1_TYPE asn1_struct, const char *where,
610 const void *_data, int sizeof_data)
612 char tmp[128];
613 int result;
615 /* write the data (value)
618 _gnutls_str_cpy (tmp, sizeof (tmp), where);
619 _gnutls_str_cat (tmp, sizeof (tmp), ".value");
621 result = asn1_write_value (asn1_struct, tmp, _data, sizeof_data);
622 if (result < 0)
624 gnutls_assert ();
625 return _gnutls_asn2err (result);
628 /* write the type
630 _gnutls_str_cpy (tmp, sizeof (tmp), where);
631 _gnutls_str_cat (tmp, sizeof (tmp), ".type");
633 result = asn1_write_value (asn1_struct, tmp, given_oid, 1);
634 if (result != ASN1_SUCCESS)
636 gnutls_assert ();
637 return _gnutls_asn2err (result);
640 return 0;
644 /* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
645 * otherwise.
647 * octet_string should be non-zero if we are to decode octet strings after
648 * decoding.
650 * The output is allocated and stored in value.
653 _gnutls_x509_decode_and_read_attribute (ASN1_TYPE asn1_struct,
654 const char *where, char *oid,
655 int oid_size, gnutls_datum_t * value,
656 int multi, int octet_string)
658 char tmpbuffer[128];
659 int len, result;
661 /* Read the OID
663 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
664 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".type");
666 len = oid_size - 1;
667 result = asn1_read_value (asn1_struct, tmpbuffer, oid, &len);
669 if (result != ASN1_SUCCESS)
671 gnutls_assert ();
672 result = _gnutls_asn2err (result);
673 return result;
676 /* Read the Value
679 _gnutls_str_cpy (tmpbuffer, sizeof (tmpbuffer), where);
680 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), ".value");
682 if (multi)
683 _gnutls_str_cat (tmpbuffer, sizeof (tmpbuffer), "s.?1"); /* .values.?1 */
685 if (octet_string)
686 result = _gnutls_x509_read_string (asn1_struct, tmpbuffer, value, ASN1_ETYPE_OCTET_STRING);
687 else
688 result = _gnutls_x509_read_value (asn1_struct, tmpbuffer, value);
689 if (result < 0)
691 gnutls_assert ();
692 return result;
695 return 0;
699 /* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN.
700 * The input is assumed to be raw data.
702 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer".
703 * That is to point before the rndSequence.
707 _gnutls_x509_set_dn_oid (ASN1_TYPE asn1_struct,
708 const char *asn1_name, const char *given_oid,
709 int raw_flag, const char *name, int sizeof_name)
711 int result;
712 char tmp[ASN1_MAX_NAME_SIZE], asn1_rdn_name[ASN1_MAX_NAME_SIZE];
714 if (sizeof_name == 0 || name == NULL)
716 gnutls_assert ();
717 return GNUTLS_E_INVALID_REQUEST;
720 /* create the rdnSequence
722 result = asn1_write_value (asn1_struct, asn1_name, "rdnSequence", 1);
723 if (result != ASN1_SUCCESS)
725 gnutls_assert ();
726 return _gnutls_asn2err (result);
729 _gnutls_str_cpy (asn1_rdn_name, sizeof (asn1_rdn_name), asn1_name);
730 _gnutls_str_cat (asn1_rdn_name, sizeof (asn1_rdn_name), ".rdnSequence");
732 /* create a new element
734 result = asn1_write_value (asn1_struct, asn1_rdn_name, "NEW", 1);
735 if (result != ASN1_SUCCESS)
737 gnutls_assert ();
738 return _gnutls_asn2err (result);
741 _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name);
742 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST");
744 /* create the set with only one element
746 result = asn1_write_value (asn1_struct, tmp, "NEW", 1);
747 if (result != ASN1_SUCCESS)
749 gnutls_assert ();
750 return _gnutls_asn2err (result);
754 /* Encode and write the data
756 _gnutls_str_cpy (tmp, sizeof (tmp), asn1_rdn_name);
757 _gnutls_str_cat (tmp, sizeof (tmp), ".?LAST.?LAST");
759 if (!raw_flag)
761 result =
762 _gnutls_x509_encode_and_write_attribute (given_oid,
763 asn1_struct,
764 tmp, name, sizeof_name, 0);
766 else
768 result =
769 _gnutls_x509_write_attribute (given_oid, asn1_struct,
770 tmp, name, sizeof_name);
773 if (result < 0)
775 gnutls_assert ();
776 return result;
779 return 0;
783 * gnutls_x509_dn_init:
784 * @dn: the object to be initialized
786 * This function initializes a #gnutls_x509_dn_t structure.
788 * The object returned must be deallocated using
789 * gnutls_x509_dn_deinit().
791 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
792 * negative error value.
794 * Since: 2.4.0
797 gnutls_x509_dn_init (gnutls_x509_dn_t * dn)
799 int result;
800 ASN1_TYPE tmpdn = ASN1_TYPE_EMPTY;
802 if ((result =
803 asn1_create_element (_gnutls_get_pkix (),
804 "PKIX1.Name", &tmpdn)) != ASN1_SUCCESS)
806 gnutls_assert ();
807 return _gnutls_asn2err (result);
810 *dn = tmpdn;
812 return 0;
816 * gnutls_x509_dn_import:
817 * @dn: the structure that will hold the imported DN
818 * @data: should contain a DER encoded RDN sequence
820 * This function parses an RDN sequence and stores the result to a
821 * #gnutls_x509_dn_t structure. The structure must have been initialized
822 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
823 * decode the DN.
825 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
826 * negative error value.
828 * Since: 2.4.0
831 gnutls_x509_dn_import (gnutls_x509_dn_t dn, const gnutls_datum_t * data)
833 int result;
834 char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
836 result = asn1_der_decoding ((ASN1_TYPE *) & dn,
837 data->data, data->size, err);
838 if (result != ASN1_SUCCESS)
840 /* couldn't decode DER */
841 _gnutls_debug_log ("ASN.1 Decoding error: %s\n", err);
842 gnutls_assert ();
843 return _gnutls_asn2err (result);
846 return 0;
850 * gnutls_x509_dn_deinit:
851 * @dn: a DN uint8_t object pointer.
853 * This function deallocates the DN object as returned by
854 * gnutls_x509_dn_import().
856 * Since: 2.4.0
858 void
859 gnutls_x509_dn_deinit (gnutls_x509_dn_t dn)
861 asn1_delete_structure ((ASN1_TYPE *) & dn);
865 * gnutls_x509_rdn_get:
866 * @idn: should contain a DER encoded RDN sequence
867 * @buf: a pointer to a structure to hold the peer's name
868 * @sizeof_buf: holds the size of @buf
870 * This function will return the name of the given RDN sequence. The
871 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
872 * RFC4514.
874 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
875 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
876 * updated if the provided buffer is not long enough, otherwise a
877 * negative error value.
880 gnutls_x509_rdn_get (const gnutls_datum_t * idn,
881 char *buf, size_t * sizeof_buf)
883 int result;
884 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
886 if (sizeof_buf == 0)
888 gnutls_assert ();
889 return GNUTLS_E_INVALID_REQUEST;
892 if (buf)
893 buf[0] = 0;
896 if ((result =
897 asn1_create_element (_gnutls_get_pkix (),
898 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
900 gnutls_assert ();
901 return _gnutls_asn2err (result);
904 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
905 if (result != ASN1_SUCCESS)
907 /* couldn't decode DER */
908 gnutls_assert ();
909 asn1_delete_structure (&dn);
910 return _gnutls_asn2err (result);
913 result = _gnutls_x509_parse_dn (dn, "rdnSequence", buf, sizeof_buf);
915 asn1_delete_structure (&dn);
916 return result;
921 * gnutls_x509_rdn_get_by_oid:
922 * @idn: should contain a DER encoded RDN sequence
923 * @oid: an Object Identifier
924 * @indx: In case multiple same OIDs exist in the RDN indicates which
925 * to send. Use 0 for the first one.
926 * @raw_flag: If non-zero then the raw DER data are returned.
927 * @buf: a pointer to a structure to hold the peer's name
928 * @sizeof_buf: holds the size of @buf
930 * This function will return the name of the given Object identifier,
931 * of the RDN sequence. The name will be encoded using the rules
932 * from RFC4514.
934 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
935 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
936 * updated if the provided buffer is not long enough, otherwise a
937 * negative error value.
940 gnutls_x509_rdn_get_by_oid (const gnutls_datum_t * idn, const char *oid,
941 int indx, unsigned int raw_flag,
942 void *buf, size_t * sizeof_buf)
944 int result;
945 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
946 gnutls_datum_t td;
948 if (sizeof_buf == 0)
950 return GNUTLS_E_INVALID_REQUEST;
953 if ((result =
954 asn1_create_element (_gnutls_get_pkix (),
955 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
957 gnutls_assert ();
958 return _gnutls_asn2err (result);
961 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
962 if (result != ASN1_SUCCESS)
964 /* couldn't decode DER */
965 gnutls_assert ();
966 asn1_delete_structure (&dn);
967 return _gnutls_asn2err (result);
970 result =
971 _gnutls_x509_parse_dn_oid (dn, "rdnSequence", oid, indx,
972 raw_flag, &td);
974 asn1_delete_structure (&dn);
975 if (result < 0)
976 return gnutls_assert_val(result);
978 return _gnutls_strdatum_to_buf (&td, buf, sizeof_buf);
982 * gnutls_x509_rdn_get_oid:
983 * @idn: should contain a DER encoded RDN sequence
984 * @indx: Indicates which OID to return. Use 0 for the first one.
985 * @buf: a pointer to a structure to hold the peer's name OID
986 * @sizeof_buf: holds the size of @buf
988 * This function will return the specified Object identifier, of the
989 * RDN sequence.
991 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
992 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@sizeof_buf is
993 * updated if the provided buffer is not long enough, otherwise a
994 * negative error value.
996 * Since: 2.4.0
999 gnutls_x509_rdn_get_oid (const gnutls_datum_t * idn,
1000 int indx, void *buf, size_t * sizeof_buf)
1002 int result;
1003 ASN1_TYPE dn = ASN1_TYPE_EMPTY;
1005 if (sizeof_buf == 0)
1007 return GNUTLS_E_INVALID_REQUEST;
1010 if ((result =
1011 asn1_create_element (_gnutls_get_pkix (),
1012 "PKIX1.Name", &dn)) != ASN1_SUCCESS)
1014 gnutls_assert ();
1015 return _gnutls_asn2err (result);
1018 result = asn1_der_decoding (&dn, idn->data, idn->size, NULL);
1019 if (result != ASN1_SUCCESS)
1021 /* couldn't decode DER */
1022 gnutls_assert ();
1023 asn1_delete_structure (&dn);
1024 return _gnutls_asn2err (result);
1027 result = _gnutls_x509_get_dn_oid (dn, "rdnSequence", indx, buf, sizeof_buf);
1029 asn1_delete_structure (&dn);
1030 return result;
1035 * Compares the DER encoded part of a DN.
1037 * FIXME: use a real DN comparison algorithm.
1039 * Returns 1 if the DN's match and (0) if they don't match. Otherwise
1040 * a negative error code is returned to indicate error.
1043 _gnutls_x509_compare_raw_dn (const gnutls_datum_t * dn1,
1044 const gnutls_datum_t * dn2)
1047 if (dn1->size != dn2->size)
1049 gnutls_assert ();
1050 return 0;
1052 if (memcmp (dn1->data, dn2->data, dn2->size) != 0)
1054 gnutls_assert ();
1055 return 0;
1057 return 1; /* they match */
1061 * gnutls_x509_dn_export:
1062 * @dn: Holds the uint8_t DN object
1063 * @format: the format of output params. One of PEM or DER.
1064 * @output_data: will contain a DN PEM or DER encoded
1065 * @output_data_size: holds the size of output_data (and will be
1066 * replaced by the actual size of parameters)
1068 * This function will export the DN to DER or PEM format.
1070 * If the buffer provided is not long enough to hold the output, then
1071 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
1072 * will be returned.
1074 * If the structure is PEM encoded, it will have a header
1075 * of "BEGIN NAME".
1077 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1078 * negative error value.
1081 gnutls_x509_dn_export (gnutls_x509_dn_t dn,
1082 gnutls_x509_crt_fmt_t format, void *output_data,
1083 size_t * output_data_size)
1085 ASN1_TYPE asn1 = dn;
1087 if (asn1 == NULL)
1089 gnutls_assert ();
1090 return GNUTLS_E_INVALID_REQUEST;
1093 return _gnutls_x509_export_int_named (asn1, "rdnSequence",
1094 format, "NAME",
1095 output_data, output_data_size);
1099 * gnutls_x509_dn_export2:
1100 * @dn: Holds the uint8_t DN object
1101 * @format: the format of output params. One of PEM or DER.
1102 * @out: will contain a DN PEM or DER encoded
1104 * This function will export the DN to DER or PEM format.
1106 * The output buffer is allocated using gnutls_malloc().
1108 * If the structure is PEM encoded, it will have a header
1109 * of "BEGIN NAME".
1111 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1112 * negative error value.
1115 gnutls_x509_dn_export2 (gnutls_x509_dn_t dn,
1116 gnutls_x509_crt_fmt_t format, gnutls_datum_t *out)
1118 ASN1_TYPE asn1 = dn;
1120 if (asn1 == NULL)
1122 gnutls_assert ();
1123 return GNUTLS_E_INVALID_REQUEST;
1126 return _gnutls_x509_export_int_named2 (asn1, "rdnSequence",
1127 format, "NAME", out);