Coverage Report

Created: 2023-03-26 08:33

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