Coverage Report

Created: 2025-03-18 06:55

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