1 /*
2 * Copyright (C) 2013-2016 Nikos Mavrogiannopoulos
3 * Copyright (C) 2016 Red Hat, Inc.
4 *
5 * This file is part of GnuTLS.
6 *
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>
19 *
20 */
21
22 /* This file contains functions to handle X.509 certificate generation.
23 */
24
25 #include "gnutls_int.h"
26
27 #include <datum.h>
28 #include <global.h>
29 #include "errors.h"
30 #include <common.h>
31 #include <x509.h>
32 #include <x509_b64.h>
33 #include <c-ctype.h>
34
35 typedef int (*set_dn_func) (void *, const char *oid, unsigned int raw_flag,
36 const void *name, unsigned int name_size);
37
38 static
dn_attr_crt_set(set_dn_func f,void * crt,const gnutls_datum_t * name,const gnutls_datum_t * val,unsigned is_raw)39 int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t * name,
40 const gnutls_datum_t * val, unsigned is_raw)
41 {
42 char _oid[MAX_OID_SIZE];
43 gnutls_datum_t tmp;
44 const char *oid;
45 int ret;
46 unsigned i,j;
47
48 if (name->size == 0 || val->size == 0)
49 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
50
51 if (c_isdigit(name->data[0]) != 0) {
52 if (name->size >= sizeof(_oid))
53 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
54
55 memcpy(_oid, name->data, name->size);
56 _oid[name->size] = 0;
57
58 oid = _oid;
59
60 if (gnutls_x509_dn_oid_known(oid) == 0 && !is_raw) {
61 _gnutls_debug_log("Unknown OID: '%s'\n", oid);
62 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
63 }
64 } else {
65 oid =
66 _gnutls_ldap_string_to_oid((char *) name->data,
67 name->size);
68 }
69
70 if (oid == NULL) {
71 _gnutls_debug_log("Unknown DN attribute: '%.*s'\n",
72 (int) name->size, name->data);
73 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
74 }
75
76 if (is_raw) {
77 gnutls_datum_t hex = {val->data+1, val->size-1};
78
79 ret = gnutls_hex_decode2(&hex, &tmp);
80 if (ret < 0)
81 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
82 } else {
83 tmp.size = val->size;
84 tmp.data = gnutls_malloc(tmp.size+1);
85 if (tmp.data == NULL) {
86 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
87 }
88
89 /* unescape */
90 for (j=i=0;i<tmp.size;i++) {
91 if (1+j!=val->size && val->data[j] == '\\') {
92 if (val->data[j+1] == ',' || val->data[j+1] == '#' ||
93 val->data[j+1] == ' ' || val->data[j+1] == '+' ||
94 val->data[j+1] == '"' || val->data[j+1] == '<' ||
95 val->data[j+1] == '>' || val->data[j+1] == ';' ||
96 val->data[j+1] == '\\' || val->data[j+1] == '=') {
97 tmp.data[i] = val->data[j+1];
98 j+=2;
99 tmp.size--;
100 } else {
101 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
102 goto fail;
103 }
104 } else {
105 tmp.data[i] = val->data[j++];
106 }
107 }
108 tmp.data[tmp.size] = 0;
109 }
110
111 ret = f(crt, oid, is_raw, tmp.data, tmp.size);
112 if (ret < 0) {
113 gnutls_assert();
114 goto fail;
115 }
116
117 ret = 0;
118 fail:
119 gnutls_free(tmp.data);
120 return ret;
121 }
122
read_attr_and_val(const char ** ptr,gnutls_datum_t * name,gnutls_datum_t * val,unsigned * is_raw)123 static int read_attr_and_val(const char **ptr,
124 gnutls_datum_t *name, gnutls_datum_t *val,
125 unsigned *is_raw)
126 {
127 const unsigned char *p = (void *) *ptr;
128
129 *is_raw = 0;
130
131 /* skip any space */
132 while (c_isspace(*p))
133 p++;
134
135 /* Read the name */
136 name->data = (void *) p;
137 while (*p != '=' && *p != 0 && !c_isspace(*p))
138 p++;
139
140 name->size = p - name->data;
141
142 /* skip any space */
143 while (c_isspace(*p))
144 p++;
145
146 if (*p != '=')
147 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
148 p++;
149
150 while (c_isspace(*p))
151 p++;
152
153 if (*p == '#') {
154 *is_raw = 1;
155 }
156
157 /* Read value */
158 val->data = (void *) p;
159 while (*p != 0 && (*p != ',' || (*p == ',' && *(p - 1) == '\\'))
160 && *p != '\n') {
161 p++;
162 }
163 val->size = p - (val->data);
164 *ptr = (void*)p;
165
166 p = val->data;
167 /* check for unescaped '+' - we do not support them */
168 while (*p != 0) {
169 if (*p == '+' && (*(p - 1) != '\\'))
170 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
171 p++;
172 }
173
174 /* remove spaces from the end */
175 while(val->size > 0 && c_isspace(val->data[val->size-1])) {
176 if (val->size-2 > 0 && val->data[val->size-2] == '\\')
177 break;
178 val->size--;
179 }
180
181 if (val->size == 0 || name->size == 0)
182 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
183
184 return 0;
185 }
186
187 typedef struct elem_list_st {
188 gnutls_datum_t name;
189 gnutls_datum_t val;
190 const char *pos;
191 unsigned is_raw;
192 struct elem_list_st *next;
193 } elem_list_st;
194
add_new_elem(elem_list_st ** head,const gnutls_datum_t * name,const gnutls_datum_t * val,const char * pos,unsigned is_raw)195 static int add_new_elem(elem_list_st **head, const gnutls_datum_t *name, const gnutls_datum_t *val, const char *pos, unsigned is_raw)
196 {
197 elem_list_st *elem = gnutls_malloc(sizeof(*elem));
198 if (elem == NULL)
199 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
200
201 memcpy(&elem->name, name, sizeof(*name));
202 memcpy(&elem->val, val, sizeof(*val));
203 elem->pos = pos;
204 elem->is_raw = is_raw;
205 elem->next = *head;
206 *head = elem;
207
208 return 0;
209 }
210
211 static int
crt_set_dn(set_dn_func f,void * crt,const char * dn,const char ** err)212 crt_set_dn(set_dn_func f, void *crt, const char *dn, const char **err)
213 {
214 const char *p = dn;
215 int ret;
216 gnutls_datum_t name, val;
217 unsigned is_raw;
218 elem_list_st *list = NULL, *plist, *next;
219
220 if (crt == NULL || dn == NULL)
221 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
222
223 /* We parse the string and set all elements to a linked list in
224 * reverse order. That way we can encode in reverse order,
225 * the way RFC4514 requires. */
226
227 /* For each element */
228 while (*p != 0 && *p != '\n') {
229 if (err)
230 *err = p;
231
232 is_raw = 0;
233 ret = read_attr_and_val(&p, &name, &val, &is_raw);
234 if (ret < 0) {
235 gnutls_assert();
236 goto fail;
237 }
238
239 /* skip spaces and look for comma */
240 while (c_isspace(*p))
241 p++;
242
243 ret = add_new_elem(&list, &name, &val, p, is_raw);
244 if (ret < 0) {
245 gnutls_assert();
246 goto fail;
247 }
248
249 if (*p != ',' && *p != 0 && *p != '\n') {
250 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
251 goto fail;
252 }
253 if (*p == ',')
254 p++;
255 }
256
257 plist = list;
258 while(plist) {
259 if (err)
260 *err = plist->pos;
261 ret = dn_attr_crt_set(f, crt, &plist->name, &plist->val, plist->is_raw);
262 if (ret < 0)
263 goto fail;
264
265 plist = plist->next;
266 }
267
268 ret = 0;
269 fail:
270 plist = list;
271 while(plist) {
272 next = plist->next;
273 gnutls_free(plist);
274 plist = next;
275 }
276 return ret;
277 }
278
279
280 /**
281 * gnutls_x509_crt_set_dn:
282 * @crt: a certificate of type #gnutls_x509_crt_t
283 * @dn: a comma separated DN string (RFC4514)
284 * @err: indicates the error position (if any)
285 *
286 * This function will set the DN on the provided certificate.
287 * The input string should be plain ASCII or UTF-8 encoded. On
288 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
289 *
290 * Note that DNs are not expected to hold DNS information, and thus
291 * no automatic IDNA conversions are attempted when using this function.
292 * If that is required (e.g., store a domain in CN), process the corresponding
293 * input with gnutls_idna_map().
294 *
295 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
296 * negative error value.
297 **/
298 int
gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt,const char * dn,const char ** err)299 gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt, const char *dn,
300 const char **err)
301 {
302 return crt_set_dn((set_dn_func) gnutls_x509_crt_set_dn_by_oid, crt,
303 dn, err);
304 }
305
306 /**
307 * gnutls_x509_crt_set_issuer_dn:
308 * @crt: a certificate of type #gnutls_x509_crt_t
309 * @dn: a comma separated DN string (RFC4514)
310 * @err: indicates the error position (if any)
311 *
312 * This function will set the DN on the provided certificate.
313 * The input string should be plain ASCII or UTF-8 encoded. On
314 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
315 *
316 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
317 * negative error value.
318 **/
319 int
gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt,const char * dn,const char ** err)320 gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt, const char *dn,
321 const char **err)
322 {
323 return crt_set_dn((set_dn_func)
324 gnutls_x509_crt_set_issuer_dn_by_oid, crt, dn,
325 err);
326 }
327
328 /**
329 * gnutls_x509_crq_set_dn:
330 * @crq: a certificate of type #gnutls_x509_crq_t
331 * @dn: a comma separated DN string (RFC4514)
332 * @err: indicates the error position (if any)
333 *
334 * This function will set the DN on the provided certificate.
335 * The input string should be plain ASCII or UTF-8 encoded. On
336 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
337 *
338 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
339 * negative error value.
340 **/
341 int
gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq,const char * dn,const char ** err)342 gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq, const char *dn,
343 const char **err)
344 {
345 return crt_set_dn((set_dn_func) gnutls_x509_crq_set_dn_by_oid, crq,
346 dn, err);
347 }
348
349 static
set_dn_by_oid(gnutls_x509_dn_t dn,const char * oid,unsigned int raw_flag,const void * name,unsigned name_size)350 int set_dn_by_oid(gnutls_x509_dn_t dn, const char *oid, unsigned int raw_flag, const void *name, unsigned name_size)
351 {
352 return _gnutls_x509_set_dn_oid(dn->asn, "", oid, raw_flag, name, name_size);
353 }
354
355 /**
356 * gnutls_x509_dn_set_str:
357 * @dn: a pointer to DN
358 * @str: a comma separated DN string (RFC4514)
359 * @err: indicates the error position (if any)
360 *
361 * This function will set the DN on the provided DN structure.
362 * The input string should be plain ASCII or UTF-8 encoded. On
363 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
364 *
365 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
366 * negative error value.
367 *
368 * Since: 3.5.3
369 **/
370 int
gnutls_x509_dn_set_str(gnutls_x509_dn_t dn,const char * str,const char ** err)371 gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str, const char **err)
372 {
373 if (dn == NULL) {
374 gnutls_assert();
375 return GNUTLS_E_INVALID_REQUEST;
376 }
377
378 return crt_set_dn((set_dn_func) set_dn_by_oid, dn,
379 str, err);
380 }
381
382 /**
383 * gnutls_x509_dn_init:
384 * @dn: the object to be initialized
385 *
386 * This function initializes a #gnutls_x509_dn_t type.
387 *
388 * The object returned must be deallocated using
389 * gnutls_x509_dn_deinit().
390 *
391 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
392 * negative error value.
393 *
394 * Since: 2.4.0
395 **/
gnutls_x509_dn_init(gnutls_x509_dn_t * dn)396 int gnutls_x509_dn_init(gnutls_x509_dn_t * dn)
397 {
398 int result;
399
400 *dn = gnutls_calloc(1, sizeof(gnutls_x509_dn_st));
401
402 if ((result =
403 asn1_create_element(_gnutls_get_pkix(),
404 "PKIX1.Name", &(*dn)->asn)) != ASN1_SUCCESS) {
405 gnutls_assert();
406 gnutls_free(*dn);
407 return _gnutls_asn2err(result);
408 }
409
410 return 0;
411 }
412
413 /**
414 * gnutls_x509_dn_import:
415 * @dn: the structure that will hold the imported DN
416 * @data: should contain a DER encoded RDN sequence
417 *
418 * This function parses an RDN sequence and stores the result to a
419 * #gnutls_x509_dn_t type. The data must have been initialized
420 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
421 * decode the DN.
422 *
423 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
424 * negative error value.
425 *
426 * Since: 2.4.0
427 **/
gnutls_x509_dn_import(gnutls_x509_dn_t dn,const gnutls_datum_t * data)428 int gnutls_x509_dn_import(gnutls_x509_dn_t dn, const gnutls_datum_t * data)
429 {
430 int result;
431 char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
432
433 if (data->data == NULL || data->size == 0)
434 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
435
436 result = _asn1_strict_der_decode(&dn->asn,
437 data->data, data->size, err);
438 if (result != ASN1_SUCCESS) {
439 /* couldn't decode DER */
440 _gnutls_debug_log("ASN.1 Decoding error: %s\n", err);
441 gnutls_assert();
442 return _gnutls_asn2err(result);
443 }
444
445 return 0;
446 }
447
448 /**
449 * gnutls_x509_dn_deinit:
450 * @dn: a DN uint8_t object pointer.
451 *
452 * This function deallocates the DN object as returned by
453 * gnutls_x509_dn_import().
454 *
455 * Since: 2.4.0
456 **/
gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)457 void gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)
458 {
459 asn1_delete_structure(&dn->asn);
460 gnutls_free(dn);
461 }
462
463 /**
464 * gnutls_x509_dn_export:
465 * @dn: Holds the uint8_t DN object
466 * @format: the format of output params. One of PEM or DER.
467 * @output_data: will contain a DN PEM or DER encoded
468 * @output_data_size: holds the size of output_data (and will be
469 * replaced by the actual size of parameters)
470 *
471 * This function will export the DN to DER or PEM format.
472 *
473 * If the buffer provided is not long enough to hold the output, then
474 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
475 * will be returned.
476 *
477 * If the structure is PEM encoded, it will have a header
478 * of "BEGIN NAME".
479 *
480 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
481 * negative error value.
482 **/
483 int
gnutls_x509_dn_export(gnutls_x509_dn_t dn,gnutls_x509_crt_fmt_t format,void * output_data,size_t * output_data_size)484 gnutls_x509_dn_export(gnutls_x509_dn_t dn,
485 gnutls_x509_crt_fmt_t format, void *output_data,
486 size_t * output_data_size)
487 {
488 if (dn == NULL) {
489 gnutls_assert();
490 return GNUTLS_E_INVALID_REQUEST;
491 }
492
493 return _gnutls_x509_export_int_named(dn->asn, "rdnSequence",
494 format, "NAME",
495 output_data,
496 output_data_size);
497 }
498
499 /**
500 * gnutls_x509_dn_export2:
501 * @dn: Holds the uint8_t DN object
502 * @format: the format of output params. One of PEM or DER.
503 * @out: will contain a DN PEM or DER encoded
504 *
505 * This function will export the DN to DER or PEM format.
506 *
507 * The output buffer is allocated using gnutls_malloc().
508 *
509 * If the structure is PEM encoded, it will have a header
510 * of "BEGIN NAME".
511 *
512 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
513 * negative error value.
514 *
515 * Since: 3.1.3
516 **/
517 int
gnutls_x509_dn_export2(gnutls_x509_dn_t dn,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)518 gnutls_x509_dn_export2(gnutls_x509_dn_t dn,
519 gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
520 {
521 if (dn == NULL) {
522 gnutls_assert();
523 return GNUTLS_E_INVALID_REQUEST;
524 }
525
526 return _gnutls_x509_export_int_named2(dn->asn, "rdnSequence",
527 format, "NAME", out);
528 }
529
530 /**
531 * gnutls_x509_dn_get_rdn_ava:
532 * @dn: a pointer to DN
533 * @irdn: index of RDN
534 * @iava: index of AVA.
535 * @ava: Pointer to structure which will hold output information.
536 *
537 * Get pointers to data within the DN. The format of the @ava structure
538 * is shown below.
539 *
540 * struct gnutls_x509_ava_st {
541 * gnutls_datum_t oid;
542 * gnutls_datum_t value;
543 * unsigned long value_tag;
544 * };
545 *
546 * The X.509 distinguished name is a sequence of sequences of strings
547 * and this is what the @irdn and @iava indexes model.
548 *
549 * Note that @ava will contain pointers into the @dn structure which
550 * in turns points to the original certificate. Thus you should not
551 * modify any data or deallocate any of those.
552 *
553 * This is a low-level function that requires the caller to do the
554 * value conversions when necessary (e.g. from UCS-2).
555 *
556 * Returns: Returns 0 on success, or an error code.
557 **/
558 int
gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn,int irdn,int iava,gnutls_x509_ava_st * ava)559 gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn,
560 int irdn, int iava, gnutls_x509_ava_st * ava)
561 {
562 ASN1_TYPE rdn, elem;
563 ASN1_DATA_NODE vnode;
564 long len;
565 int lenlen, remlen, ret;
566 char rbuf[MAX_NAME_SIZE];
567 unsigned char cls;
568 const unsigned char *ptr;
569
570 iava++;
571 irdn++; /* 0->1, 1->2 etc */
572
573 snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava);
574 rdn = asn1_find_node(dn->asn, rbuf);
575 if (!rdn) {
576 gnutls_assert();
577 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
578 }
579
580 snprintf(rbuf, sizeof(rbuf), "?%d.type", iava);
581 elem = asn1_find_node(rdn, rbuf);
582 if (!elem) {
583 gnutls_assert();
584 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
585 }
586
587 ret = asn1_read_node_value(elem, &vnode);
588 if (ret != ASN1_SUCCESS) {
589 gnutls_assert();
590 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
591 }
592
593 ava->oid.data = (void *) vnode.value;
594 ava->oid.size = vnode.value_len;
595
596 snprintf(rbuf, sizeof(rbuf), "?%d.value", iava);
597 elem = asn1_find_node(rdn, rbuf);
598 if (!elem) {
599 gnutls_assert();
600 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
601 }
602
603 ret = asn1_read_node_value(elem, &vnode);
604 if (ret != ASN1_SUCCESS) {
605 gnutls_assert();
606 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
607 }
608 /* The value still has the previous tag's length bytes, plus the
609 * current value's tag and length bytes. Decode them.
610 */
611
612 ptr = vnode.value;
613 remlen = vnode.value_len;
614 len = asn1_get_length_der(ptr, remlen, &lenlen);
615 if (len < 0) {
616 gnutls_assert();
617 return GNUTLS_E_ASN1_DER_ERROR;
618 }
619
620 ptr += lenlen;
621 remlen -= lenlen;
622 ret =
623 asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag);
624 if (ret) {
625 gnutls_assert();
626 return _gnutls_asn2err(ret);
627 }
628
629 ptr += lenlen;
630 remlen -= lenlen;
631
632 {
633 signed long tmp;
634
635 tmp = asn1_get_length_der(ptr, remlen, &lenlen);
636 if (tmp < 0) {
637 gnutls_assert();
638 return GNUTLS_E_ASN1_DER_ERROR;
639 }
640 ava->value.size = tmp;
641 }
642 ava->value.data = (void *) (ptr + lenlen);
643
644 return 0;
645 }
646
647 /**
648 * gnutls_x509_dn_get_str:
649 * @dn: a pointer to DN
650 * @str: a datum that will hold the name
651 *
652 * This function will allocate buffer and copy the name in the provided DN.
653 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
654 * described in RFC4514. The output string will be ASCII or UTF-8
655 * encoded, depending on the certificate data.
656 *
657 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
658 * negative error value.
659 *
660 * Since: 3.4.2
661 **/
662 int
gnutls_x509_dn_get_str(gnutls_x509_dn_t dn,gnutls_datum_t * str)663 gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str)
664 {
665 if (dn == NULL) {
666 gnutls_assert();
667 return GNUTLS_E_INVALID_REQUEST;
668 }
669
670 return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, GNUTLS_X509_DN_FLAG_COMPAT);
671 }
672
673 /**
674 * gnutls_x509_dn_get_str:
675 * @dn: a pointer to DN
676 * @str: a datum that will hold the name
677 * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
678 *
679 * This function will allocate buffer and copy the name in the provided DN.
680 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
681 * described in RFC4514. The output string will be ASCII or UTF-8
682 * encoded, depending on the certificate data.
683 *
684 * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
685 * format will match the format output by previous to 3.5.6 versions of GnuTLS
686 * which was not not fully RFC4514-compliant.
687 *
688 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
689 * negative error value.
690 *
691 * Since: 3.5.7
692 **/
693 int
gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn,gnutls_datum_t * str,unsigned flags)694 gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str, unsigned flags)
695 {
696 if (dn == NULL) {
697 gnutls_assert();
698 return GNUTLS_E_INVALID_REQUEST;
699 }
700
701 return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, flags);
702 }
703