Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/x509/dn.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2003-2014 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
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 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
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.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
#include "gnutls_int.h"
24
#include <libtasn1.h>
25
#include <datum.h>
26
#include <global.h>
27
#include "errors.h"
28
#include <str.h>
29
#include <common.h>
30
#include <num.h>
31
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 protocols!!!)
34
 */
35
36
static int append_elements(asn1_node asn1_struct, const char *asn1_rdn_name,
37
         gnutls_buffer_st * str, int k1, unsigned last)
38
0
{
39
0
  int k2, result, max_k2;
40
0
  int len;
41
0
  uint8_t value[MAX_STRING_LEN];
42
0
  char tmpbuffer1[MAX_NAME_SIZE];
43
0
  char tmpbuffer2[MAX_NAME_SIZE];
44
0
  char tmpbuffer3[MAX_NAME_SIZE];
45
0
  const char *ldap_desc;
46
0
  char oid[MAX_OID_SIZE];
47
0
  gnutls_datum_t td = { NULL, 0 };
48
0
  gnutls_datum_t tvd = { NULL, 0 };
49
50
  /* create a string like "tbsCertList.issuer.rdnSequence.?1"
51
   */
52
0
  if (asn1_rdn_name[0] != 0)
53
0
    snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%d",
54
0
       asn1_rdn_name, k1);
55
0
  else
56
0
    snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%d", k1);
57
58
0
  len = sizeof(value) - 1;
59
0
  result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
60
61
0
  if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
62
0
    gnutls_assert();
63
0
    result = _gnutls_asn2err(result);
64
0
    goto cleanup;
65
0
  }
66
67
0
  k2 = 0;
68
69
0
  result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2);
70
0
  if (result != ASN1_SUCCESS) {
71
0
    gnutls_assert();
72
0
    result = _gnutls_asn2err(result);
73
0
    goto cleanup;
74
0
  }
75
76
0
  do {     /* Move to the attribute type and values
77
         */
78
0
    k2++;
79
80
0
    if (tmpbuffer1[0] != 0)
81
0
      snprintf(tmpbuffer2, sizeof(tmpbuffer2),
82
0
         "%s.?%d", tmpbuffer1, k2);
83
0
    else
84
0
      snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%d", k2);
85
86
    /* Try to read the RelativeDistinguishedName attributes.
87
     */
88
89
0
    len = sizeof(value) - 1;
90
0
    result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len);
91
92
0
    if (result == ASN1_ELEMENT_NOT_FOUND)
93
0
      break;
94
0
    if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
95
0
      gnutls_assert();
96
0
      result = _gnutls_asn2err(result);
97
0
      goto cleanup;
98
0
    }
99
100
    /* Read the OID 
101
     */
102
0
    _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2);
103
0
    _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type");
104
105
0
    len = sizeof(oid) - 1;
106
0
    result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
107
108
0
    if (result == ASN1_ELEMENT_NOT_FOUND)
109
0
      break;
110
0
    else if (result != ASN1_SUCCESS) {
111
0
      gnutls_assert();
112
0
      result = _gnutls_asn2err(result);
113
0
      goto cleanup;
114
0
    }
115
116
    /* Read the Value 
117
     */
118
0
    _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2);
119
0
    _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value");
120
121
0
    len = 0;
122
123
0
    result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd);
124
0
    if (result < 0) {
125
0
      gnutls_assert();
126
0
      goto cleanup;
127
0
    }
128
0
#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \
129
0
  gnutls_assert(); \
130
0
  goto cleanup; \
131
0
}
132
0
#define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \
133
0
  gnutls_assert(); \
134
0
  goto cleanup; \
135
0
}
136
    /*   The encodings of adjoining RelativeDistinguishedNames are separated
137
     *   by a comma character (',' ASCII 44).
138
     */
139
140
0
    ldap_desc =
141
0
        gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID);
142
143
0
    STR_APPEND(ldap_desc);
144
0
    STR_APPEND("=");
145
146
    /* DirectoryString by definition in RFC 5280 cannot be empty.
147
     * If asn_node.value_len = 0 the parser correctly rejects such DirectoryString.
148
     * However, if asn_node.value contains ASN.1 TLV triplet with length = 0,
149
     * such DirectoryString is not rejected by the parser as the node itself is not empty.
150
     * Explicitly reject DirectoryString in such case.
151
     */
152
0
    const char *asn_desc = _gnutls_oid_get_asn_desc(oid);
153
0
    if (asn_desc && !strcmp(asn_desc, "PKIX1.DirectoryString")
154
0
        && tvd.data[1] == 0) {
155
0
      gnutls_assert();
156
0
      result = GNUTLS_E_ASN1_VALUE_NOT_VALID;
157
0
      _gnutls_debug_log("Empty DirectoryString\n");
158
0
      goto cleanup;
159
0
    }
160
161
0
    result =
162
0
        _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td);
163
0
    if (result < 0) {
164
0
      gnutls_assert();
165
0
      _gnutls_debug_log
166
0
          ("Cannot parse OID: '%s' with value '%s'\n",
167
0
           oid, _gnutls_bin2hex(tvd.data,
168
0
              tvd.size,
169
0
              tmpbuffer3,
170
0
              sizeof(tmpbuffer3), NULL));
171
0
      goto cleanup;
172
0
    }
173
174
0
    DATA_APPEND(td.data, td.size);
175
0
    _gnutls_free_datum(&td);
176
0
    _gnutls_free_datum(&tvd);
177
178
    /*   Where there is a multi-valued RDN, the outputs from adjoining
179
     *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
180
     *   character.
181
     */
182
0
    if (k2 < max_k2) {
183
0
      STR_APPEND("+");
184
0
    } else if (!last) {
185
0
      STR_APPEND(",");
186
0
    }
187
0
  }
188
0
  while (1);
189
190
0
  result = 0;
191
192
0
 cleanup:
193
0
  _gnutls_free_datum(&td);
194
0
  _gnutls_free_datum(&tvd);
195
0
  return result;
196
0
}
197
198
int
199
_gnutls_x509_get_dn(asn1_node asn1_struct,
200
        const char *asn1_rdn_name, gnutls_datum_t * dn,
201
        unsigned flags)
202
0
{
203
0
  gnutls_buffer_st out_str;
204
0
  int i, k1, result;
205
206
0
  _gnutls_buffer_init(&out_str);
207
208
0
  result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1);
209
0
  if (result != ASN1_SUCCESS) {
210
0
    if (result == ASN1_ELEMENT_NOT_FOUND
211
0
        || result == ASN1_VALUE_NOT_FOUND) {
212
0
      result =
213
0
          gnutls_assert_val
214
0
          (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
215
0
    } else {
216
0
      gnutls_assert();
217
0
      result = _gnutls_asn2err(result);
218
0
    }
219
0
    goto cleanup;
220
0
  }
221
222
0
  if (k1 == 0) {
223
0
    gnutls_assert();
224
0
    result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
225
0
    goto cleanup;
226
0
  }
227
228
0
  if (flags & GNUTLS_X509_DN_FLAG_COMPAT) {
229
0
    for (i = 0; i < k1; i++) {
230
0
      result =
231
0
          append_elements(asn1_struct, asn1_rdn_name,
232
0
              &out_str, i + 1,
233
0
              (i == (k1 - 1)) ? 1 : 0);
234
0
      if (result < 0) {
235
0
        gnutls_assert();
236
0
        goto cleanup;
237
0
      }
238
0
    }
239
0
  } else {
240
0
    while (k1 > 0) {
241
0
      result =
242
0
          append_elements(asn1_struct, asn1_rdn_name,
243
0
              &out_str, k1, k1 == 1 ? 1 : 0);
244
0
      if (result < 0) {
245
0
        gnutls_assert();
246
0
        goto cleanup;
247
0
      }
248
0
      k1--;
249
0
    }
250
0
  }
251
252
0
  return _gnutls_buffer_to_datum(&out_str, dn, 1);
253
254
0
 cleanup:
255
0
  _gnutls_buffer_clear(&out_str);
256
0
  return result;
257
258
0
}
259
260
/* Parses an X509 DN in the asn1_struct, and puts the output into
261
 * the string buf. The output is an LDAP encoded DN.
262
 *
263
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
264
 * That is to point in the rndSequence.
265
 */
266
int
267
_gnutls_x509_parse_dn(asn1_node asn1_struct,
268
          const char *asn1_rdn_name, char *buf,
269
          size_t *buf_size, unsigned flags)
270
0
{
271
0
  int ret;
272
0
  gnutls_datum_t dn = { NULL, 0 };
273
274
0
  if (buf_size == NULL) {
275
0
    gnutls_assert();
276
0
    return GNUTLS_E_INVALID_REQUEST;
277
0
  }
278
279
0
  if (*buf_size > 0 && buf)
280
0
    buf[0] = 0;
281
0
  else
282
0
    *buf_size = 0;
283
284
0
  ret = _gnutls_x509_get_dn(asn1_struct, asn1_rdn_name, &dn, flags);
285
0
  if (ret < 0)
286
0
    return gnutls_assert_val(ret);
287
288
0
  if (dn.size >= (unsigned int)*buf_size) {
289
0
    gnutls_assert();
290
0
    *buf_size = dn.size + 1;
291
0
    ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
292
0
    goto cleanup;
293
0
  }
294
295
0
  assert(dn.data != NULL);
296
297
0
  if (buf) {
298
0
    memcpy(buf, dn.data, dn.size);
299
0
    buf[dn.size] = 0;
300
0
    *buf_size = dn.size;
301
0
  } else
302
0
    *buf_size = dn.size + 1;
303
304
0
  ret = 0;
305
0
 cleanup:
306
0
  _gnutls_free_datum(&dn);
307
0
  return ret;
308
0
}
309
310
/* Parses an X509 DN in the asn1_struct, and searches for the
311
 * given OID in the DN.
312
 *
313
 * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable)
314
 * Otherwise the raw DER data are returned.
315
 *
316
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
317
 * That is to point in the rndSequence.
318
 *
319
 * indx specifies which OID to return. Ie 0 means return the first specified
320
 * OID found, 1 the second etc.
321
 */
322
int
323
_gnutls_x509_parse_dn_oid(asn1_node asn1_struct,
324
        const char *asn1_rdn_name,
325
        const char *given_oid, int indx,
326
        unsigned int raw_flag, gnutls_datum_t * out)
327
0
{
328
0
  int k2, k1, result;
329
0
  char tmpbuffer1[MAX_NAME_SIZE];
330
0
  char tmpbuffer2[MAX_NAME_SIZE];
331
0
  char tmpbuffer3[MAX_NAME_SIZE];
332
0
  gnutls_datum_t td;
333
0
  uint8_t value[256];
334
0
  char oid[MAX_OID_SIZE];
335
0
  int len;
336
0
  int i = 0;
337
338
0
  k1 = 0;
339
0
  do {
340
341
0
    k1++;
342
    /* create a string like "tbsCertList.issuer.rdnSequence.?1"
343
     */
344
0
    if (asn1_rdn_name[0] != 0)
345
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%d",
346
0
         asn1_rdn_name, k1);
347
0
    else
348
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%d", k1);
349
350
0
    len = sizeof(value) - 1;
351
0
    result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
352
353
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
354
0
      gnutls_assert();
355
0
      break;
356
0
    }
357
358
0
    if (result != ASN1_VALUE_NOT_FOUND) {
359
0
      gnutls_assert();
360
0
      result = _gnutls_asn2err(result);
361
0
      goto cleanup;
362
0
    }
363
364
0
    k2 = 0;
365
366
0
    do {   /* Move to the attribute type and values
367
         */
368
0
      k2++;
369
370
0
      if (tmpbuffer1[0] != 0)
371
0
        snprintf(tmpbuffer2, sizeof(tmpbuffer2),
372
0
           "%s.?%d", tmpbuffer1, k2);
373
0
      else
374
0
        snprintf(tmpbuffer2, sizeof(tmpbuffer2),
375
0
           "?%d", k2);
376
377
      /* Try to read the RelativeDistinguishedName attributes.
378
       */
379
380
0
      len = sizeof(value) - 1;
381
0
      result =
382
0
          asn1_read_value(asn1_struct, tmpbuffer2, value,
383
0
              &len);
384
385
0
      if (result == ASN1_ELEMENT_NOT_FOUND) {
386
0
        break;
387
0
      }
388
0
      if (result != ASN1_VALUE_NOT_FOUND) {
389
0
        gnutls_assert();
390
0
        result = _gnutls_asn2err(result);
391
0
        goto cleanup;
392
0
      }
393
394
      /* Read the OID 
395
       */
396
0
      _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
397
0
          tmpbuffer2);
398
0
      _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
399
0
          ".type");
400
401
0
      len = sizeof(oid) - 1;
402
0
      result =
403
0
          asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
404
405
0
      if (result == ASN1_ELEMENT_NOT_FOUND)
406
0
        break;
407
0
      else if (result != ASN1_SUCCESS) {
408
0
        gnutls_assert();
409
0
        result = _gnutls_asn2err(result);
410
0
        goto cleanup;
411
0
      }
412
413
0
      if (strcmp(oid, given_oid) == 0 && indx == i++) { /* Found the OID */
414
415
        /* Read the Value 
416
         */
417
0
        _gnutls_str_cpy(tmpbuffer3,
418
0
            sizeof(tmpbuffer3), tmpbuffer2);
419
0
        _gnutls_str_cat(tmpbuffer3,
420
0
            sizeof(tmpbuffer3), ".value");
421
422
0
        result =
423
0
            _gnutls_x509_read_value(asn1_struct,
424
0
                  tmpbuffer3, &td);
425
0
        if (result < 0) {
426
0
          gnutls_assert();
427
0
          goto cleanup;
428
0
        }
429
430
0
        if (raw_flag != 0) {
431
0
          out->data = td.data;
432
0
          out->size = td.size;
433
0
          return 0;
434
435
0
        } else { /* parse data. raw_flag == 0 */
436
0
          result =
437
0
              _gnutls_x509_dn_to_string(oid,
438
0
                      td.data,
439
0
                      td.size,
440
0
                      out);
441
442
0
          _gnutls_free_datum(&td);
443
0
          if (result < 0) {
444
0
            gnutls_assert();
445
0
            goto cleanup;
446
0
          }
447
448
0
          return 0;
449
450
0
        } /* raw_flag == 0 */
451
0
      }
452
0
    }
453
0
    while (1);
454
455
0
  }
456
0
  while (1);
457
458
0
  gnutls_assert();
459
460
0
  result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
461
462
0
 cleanup:
463
0
  return result;
464
0
}
465
466
/* Parses an X509 DN in the asn1_struct, and returns the requested
467
 * DN OID.
468
 *
469
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
470
 * That is to point in the rndSequence.
471
 *
472
 * indx specifies which OID to return. Ie 0 means return the first specified
473
 * OID found, 1 the second etc.
474
 */
475
int
476
_gnutls_x509_get_dn_oid(asn1_node asn1_struct,
477
      const char *asn1_rdn_name,
478
      int indx, void *_oid, size_t *sizeof_oid)
479
0
{
480
0
  int k2, k1, result;
481
0
  char tmpbuffer1[MAX_NAME_SIZE];
482
0
  char tmpbuffer2[MAX_NAME_SIZE];
483
0
  char tmpbuffer3[MAX_NAME_SIZE];
484
0
  char value[256];
485
0
  char oid[MAX_OID_SIZE];
486
0
  int len;
487
0
  int i = 0;
488
489
0
  k1 = 0;
490
0
  do {
491
492
0
    k1++;
493
    /* create a string like "tbsCertList.issuer.rdnSequence.?1"
494
     */
495
0
    if (asn1_rdn_name[0] != 0)
496
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%d",
497
0
         asn1_rdn_name, k1);
498
0
    else
499
0
      snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%d", k1);
500
501
0
    len = sizeof(value) - 1;
502
0
    result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
503
504
0
    if (result == ASN1_ELEMENT_NOT_FOUND) {
505
0
      gnutls_assert();
506
0
      break;
507
0
    }
508
509
0
    if (result != ASN1_VALUE_NOT_FOUND) {
510
0
      gnutls_assert();
511
0
      result = _gnutls_asn2err(result);
512
0
      goto cleanup;
513
0
    }
514
515
0
    k2 = 0;
516
517
0
    do {   /* Move to the attribute type and values
518
         */
519
0
      k2++;
520
521
0
      if (tmpbuffer1[0] != 0)
522
0
        snprintf(tmpbuffer2, sizeof(tmpbuffer2),
523
0
           "%s.?%d", tmpbuffer1, k2);
524
0
      else
525
0
        snprintf(tmpbuffer2, sizeof(tmpbuffer2),
526
0
           "?%d", k2);
527
528
      /* Try to read the RelativeDistinguishedName attributes.
529
       */
530
531
0
      len = sizeof(value) - 1;
532
0
      result =
533
0
          asn1_read_value(asn1_struct, tmpbuffer2, value,
534
0
              &len);
535
536
0
      if (result == ASN1_ELEMENT_NOT_FOUND) {
537
0
        break;
538
0
      }
539
0
      if (result != ASN1_VALUE_NOT_FOUND) {
540
0
        gnutls_assert();
541
0
        result = _gnutls_asn2err(result);
542
0
        goto cleanup;
543
0
      }
544
545
      /* Read the OID 
546
       */
547
0
      _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
548
0
          tmpbuffer2);
549
0
      _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
550
0
          ".type");
551
552
0
      len = sizeof(oid) - 1;
553
0
      result =
554
0
          asn1_read_value(asn1_struct, tmpbuffer3, oid, &len);
555
556
0
      if (result == ASN1_ELEMENT_NOT_FOUND)
557
0
        break;
558
0
      else if (result != ASN1_SUCCESS) {
559
0
        gnutls_assert();
560
0
        result = _gnutls_asn2err(result);
561
0
        goto cleanup;
562
0
      }
563
564
0
      if (indx == i++) { /* Found the OID */
565
566
0
        len = strlen(oid) + 1;
567
568
0
        if (*sizeof_oid < (unsigned)len) {
569
0
          *sizeof_oid = len;
570
0
          gnutls_assert();
571
0
          return GNUTLS_E_SHORT_MEMORY_BUFFER;
572
0
        }
573
574
0
        memcpy(_oid, oid, len);
575
0
        *sizeof_oid = len - 1;
576
577
0
        return 0;
578
0
      }
579
0
    }
580
0
    while (1);
581
582
0
  }
583
0
  while (1);
584
585
0
  gnutls_assert();
586
587
0
  result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
588
589
0
 cleanup:
590
0
  return result;
591
0
}
592
593
/* This will write the AttributeTypeAndValue field. The data must be already DER encoded.
594
 * 'multi' must be (0) if writing an AttributeTypeAndValue, and 1 if Attribute.
595
 * In all cases only one value is written.
596
 */
597
static int
598
_gnutls_x509_write_attribute(const char *given_oid,
599
           asn1_node asn1_struct, const char *where,
600
           const void *_data, int sizeof_data)
601
0
{
602
0
  char tmp[128];
603
0
  int result;
604
605
  /* write the data (value)
606
   */
607
608
0
  _gnutls_str_cpy(tmp, sizeof(tmp), where);
609
0
  _gnutls_str_cat(tmp, sizeof(tmp), ".value");
610
611
0
  result = asn1_write_value(asn1_struct, tmp, _data, sizeof_data);
612
0
  if (result < 0) {
613
0
    gnutls_assert();
614
0
    return _gnutls_asn2err(result);
615
0
  }
616
617
  /* write the type
618
   */
619
0
  _gnutls_str_cpy(tmp, sizeof(tmp), where);
620
0
  _gnutls_str_cat(tmp, sizeof(tmp), ".type");
621
622
0
  result = asn1_write_value(asn1_struct, tmp, given_oid, 1);
623
0
  if (result != ASN1_SUCCESS) {
624
0
    gnutls_assert();
625
0
    return _gnutls_asn2err(result);
626
0
  }
627
628
0
  return 0;
629
0
}
630
631
/* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue
632
 * otherwise.
633
 *
634
 * octet_string should be non-zero if we are to decode octet strings after
635
 * decoding.
636
 *
637
 * The output is allocated and stored in value.
638
 */
639
int
640
_gnutls_x509_decode_and_read_attribute(asn1_node asn1_struct,
641
               const char *where, char *oid,
642
               int oid_size,
643
               gnutls_datum_t * value, int multi,
644
               int octet_string)
645
0
{
646
0
  char tmpbuffer[128];
647
0
  int len, result;
648
649
  /* Read the OID 
650
   */
651
0
  _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where);
652
0
  _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".type");
653
654
0
  len = oid_size - 1;
655
0
  result = asn1_read_value(asn1_struct, tmpbuffer, oid, &len);
656
657
0
  if (result != ASN1_SUCCESS) {
658
0
    gnutls_assert();
659
0
    result = _gnutls_asn2err(result);
660
0
    return result;
661
0
  }
662
663
  /* Read the Value 
664
   */
665
666
0
  _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where);
667
0
  _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".value");
668
669
0
  if (multi)
670
0
    _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), "s.?1"); /* .values.?1 */
671
672
0
  if (octet_string)
673
0
    result =
674
0
        _gnutls_x509_read_string(asn1_struct, tmpbuffer, value,
675
0
               ASN1_ETYPE_OCTET_STRING, 0);
676
0
  else
677
0
    result = _gnutls_x509_read_value(asn1_struct, tmpbuffer, value);
678
0
  if (result < 0) {
679
0
    gnutls_assert();
680
0
    return result;
681
0
  }
682
683
0
  return 0;
684
685
0
}
686
687
/* Sets an X509 DN in the asn1_struct, and puts the given OID in the DN.
688
 * The input is assumed to be raw data.
689
 *
690
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer".
691
 * That is to point before the rndSequence.
692
 *
693
 */
694
int
695
_gnutls_x509_set_dn_oid(asn1_node asn1_struct,
696
      const char *asn1_name, const char *given_oid,
697
      int raw_flag, const char *name, int sizeof_name)
698
0
{
699
0
  int result;
700
0
  char tmp[MAX_NAME_SIZE], asn1_rdn_name[MAX_NAME_SIZE];
701
702
0
  if (sizeof_name == 0 || name == NULL) {
703
0
    gnutls_assert();
704
0
    return GNUTLS_E_INVALID_REQUEST;
705
0
  }
706
707
  /* create the rdnSequence
708
   */
709
0
  result = asn1_write_value(asn1_struct, asn1_name, "rdnSequence", 1);
710
0
  if (result != ASN1_SUCCESS) {
711
0
    gnutls_assert();
712
0
    return _gnutls_asn2err(result);
713
0
  }
714
715
0
  if (asn1_name[0] != 0) {
716
0
    _gnutls_str_cpy(asn1_rdn_name, sizeof(asn1_rdn_name),
717
0
        asn1_name);
718
0
    _gnutls_str_cat(asn1_rdn_name, sizeof(asn1_rdn_name),
719
0
        ".rdnSequence");
720
0
  } else {
721
0
    _gnutls_str_cpy(asn1_rdn_name, sizeof(asn1_rdn_name),
722
0
        "rdnSequence");
723
0
  }
724
725
  /* create a new element 
726
   */
727
0
  result = asn1_write_value(asn1_struct, asn1_rdn_name, "NEW", 1);
728
0
  if (result != ASN1_SUCCESS) {
729
0
    gnutls_assert();
730
0
    return _gnutls_asn2err(result);
731
0
  }
732
733
0
  _gnutls_str_cpy(tmp, sizeof(tmp), asn1_rdn_name);
734
0
  _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST");
735
736
  /* create the set with only one element
737
   */
738
0
  result = asn1_write_value(asn1_struct, tmp, "NEW", 1);
739
0
  if (result != ASN1_SUCCESS) {
740
0
    gnutls_assert();
741
0
    return _gnutls_asn2err(result);
742
0
  }
743
744
  /* Encode and write the data
745
   */
746
0
  _gnutls_str_cpy(tmp, sizeof(tmp), asn1_rdn_name);
747
0
  _gnutls_str_cat(tmp, sizeof(tmp), ".?LAST.?LAST");
748
749
0
  if (!raw_flag) {
750
0
    result =
751
0
        _gnutls_x509_encode_and_write_attribute(given_oid,
752
0
                  asn1_struct,
753
0
                  tmp, name,
754
0
                  sizeof_name, 0);
755
0
  } else {
756
0
    result =
757
0
        _gnutls_x509_write_attribute(given_oid, asn1_struct,
758
0
             tmp, name, sizeof_name);
759
0
  }
760
761
0
  if (result < 0) {
762
0
    gnutls_assert();
763
0
    return result;
764
0
  }
765
766
0
  return 0;
767
0
}
768
769
/**
770
 * gnutls_x509_rdn_get:
771
 * @idn: should contain a DER encoded RDN sequence
772
 * @buf: a pointer to a structure to hold the peer's name
773
 * @buf_size: holds the size of @buf
774
 *
775
 * This function will return the name of the given RDN sequence.  The
776
 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
777
 * RFC4514.
778
 *
779
 * This function does not output a fully RFC4514 compliant string, if
780
 * that is required see gnutls_x509_rdn_get2().
781
 *
782
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
783
 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
784
 * updated if the provided buffer is not long enough, otherwise a
785
 * negative error value.
786
 **/
787
int gnutls_x509_rdn_get(const gnutls_datum_t * idn, char *buf, size_t *buf_size)
788
0
{
789
0
  int ret;
790
0
  gnutls_datum_t out;
791
792
0
  ret = gnutls_x509_rdn_get2(idn, &out, GNUTLS_X509_DN_FLAG_COMPAT);
793
0
  if (ret < 0)
794
0
    return gnutls_assert_val(ret);
795
796
0
  ret = _gnutls_copy_string(&out, (void *)buf, buf_size);
797
0
  gnutls_free(out.data);
798
0
  if (ret < 0) {
799
0
    gnutls_assert();
800
0
  }
801
802
0
  return ret;
803
0
}
804
805
/**
806
 * gnutls_x509_rdn_get2:
807
 * @idn: should contain a DER encoded RDN sequence
808
 * @str: a datum that will hold the name
809
 * @flags: zero of %GNUTLS_X509_DN_FLAG_COMPAT
810
 *
811
 * This function will return the name of the given RDN sequence.  The
812
 * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
813
 * RFC4514.
814
 *
815
 * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
816
 * format will match the format output by previous to 3.5.6 versions of GnuTLS
817
 * which was not not fully RFC4514-compliant.
818
 *
819
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
820
 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
821
 * updated if the provided buffer is not long enough, otherwise a
822
 * negative error value.
823
 **/
824
int
825
gnutls_x509_rdn_get2(const gnutls_datum_t * idn,
826
         gnutls_datum_t * str, unsigned flags)
827
0
{
828
0
  int ret;
829
0
  gnutls_x509_dn_t dn;
830
831
0
  ret = gnutls_x509_dn_init(&dn);
832
0
  if (ret < 0)
833
0
    return gnutls_assert_val(ret);
834
835
0
  ret = gnutls_x509_dn_import(dn, idn);
836
0
  if (ret < 0) {
837
0
    gnutls_assert();
838
0
    goto cleanup;
839
0
  }
840
841
0
  ret = gnutls_x509_dn_get_str2(dn, str, flags);
842
0
  if (ret < 0) {
843
0
    gnutls_assert();
844
0
    goto cleanup;
845
0
  }
846
847
0
  ret = 0;
848
0
 cleanup:
849
0
  gnutls_x509_dn_deinit(dn);
850
0
  return ret;
851
0
}
852
853
/**
854
 * gnutls_x509_rdn_get_by_oid:
855
 * @idn: should contain a DER encoded RDN sequence
856
 * @oid: an Object Identifier
857
 * @indx: In case multiple same OIDs exist in the RDN indicates which
858
 *   to send. Use 0 for the first one.
859
 * @raw_flag: If non-zero then the raw DER data are returned.
860
 * @buf: a pointer to a structure to hold the peer's name
861
 * @buf_size: holds the size of @buf
862
 *
863
 * This function will return the name of the given Object identifier,
864
 * of the RDN sequence.  The name will be encoded using the rules
865
 * from RFC4514.
866
 *
867
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
868
 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
869
 * updated if the provided buffer is not long enough, otherwise a
870
 * negative error value.
871
 **/
872
int
873
gnutls_x509_rdn_get_by_oid(const gnutls_datum_t * idn, const char *oid,
874
         unsigned indx, unsigned int raw_flag,
875
         void *buf, size_t *buf_size)
876
0
{
877
0
  int result;
878
0
  asn1_node dn = NULL;
879
0
  gnutls_datum_t td;
880
881
0
  if (buf_size == 0) {
882
0
    return GNUTLS_E_INVALID_REQUEST;
883
0
  }
884
885
0
  if ((result =
886
0
       asn1_create_element(_gnutls_get_pkix(),
887
0
         "PKIX1.Name", &dn)) != ASN1_SUCCESS) {
888
0
    gnutls_assert();
889
0
    return _gnutls_asn2err(result);
890
0
  }
891
892
0
  result = _asn1_strict_der_decode(&dn, idn->data, idn->size, NULL);
893
0
  if (result != ASN1_SUCCESS) {
894
    /* couldn't decode DER */
895
0
    gnutls_assert();
896
0
    asn1_delete_structure(&dn);
897
0
    return _gnutls_asn2err(result);
898
0
  }
899
900
0
  result =
901
0
      _gnutls_x509_parse_dn_oid(dn, "rdnSequence", oid, indx,
902
0
              raw_flag, &td);
903
904
0
  asn1_delete_structure(&dn);
905
0
  if (result < 0)
906
0
    return gnutls_assert_val(result);
907
908
0
  return _gnutls_strdatum_to_buf(&td, buf, buf_size);
909
0
}
910
911
/**
912
 * gnutls_x509_rdn_get_oid:
913
 * @idn: should contain a DER encoded RDN sequence
914
 * @indx: Indicates which OID to return. Use 0 for the first one.
915
 * @buf: a pointer to a structure to hold the peer's name OID
916
 * @buf_size: holds the size of @buf
917
 *
918
 * This function will return the specified Object identifier, of the
919
 * RDN sequence.
920
 *
921
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
922
 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
923
 * updated if the provided buffer is not long enough, otherwise a
924
 * negative error value.
925
 *
926
 * Since: 2.4.0
927
 **/
928
int
929
gnutls_x509_rdn_get_oid(const gnutls_datum_t * idn,
930
      unsigned indx, void *buf, size_t *buf_size)
931
0
{
932
0
  int result;
933
0
  asn1_node dn = NULL;
934
935
0
  if (buf_size == 0) {
936
0
    return GNUTLS_E_INVALID_REQUEST;
937
0
  }
938
939
0
  if ((result =
940
0
       asn1_create_element(_gnutls_get_pkix(),
941
0
         "PKIX1.Name", &dn)) != ASN1_SUCCESS) {
942
0
    gnutls_assert();
943
0
    return _gnutls_asn2err(result);
944
0
  }
945
946
0
  result = _asn1_strict_der_decode(&dn, idn->data, idn->size, NULL);
947
0
  if (result != ASN1_SUCCESS) {
948
    /* couldn't decode DER */
949
0
    gnutls_assert();
950
0
    asn1_delete_structure(&dn);
951
0
    return _gnutls_asn2err(result);
952
0
  }
953
954
0
  result =
955
0
      _gnutls_x509_get_dn_oid(dn, "rdnSequence", indx, buf, buf_size);
956
957
0
  asn1_delete_structure(&dn);
958
0
  return result;
959
0
}
960
961
/*
962
 * Compares the DER encoded part of a DN.
963
 *
964
 * Returns 1 if the DN's match and (0) if they don't match. Otherwise
965
 * a negative error code is returned to indicate error.
966
 */
967
int
968
_gnutls_x509_compare_raw_dn(const gnutls_datum_t * dn1,
969
          const gnutls_datum_t * dn2)
970
0
{
971
0
  int ret;
972
0
  gnutls_datum_t str1, str2;
973
974
  /* Simple case of completely identical? */
975
976
0
  if (dn1->size == dn2->size) {
977
0
    if (memcmp(dn1->data, dn2->data, dn2->size) == 0) {
978
0
      return 1;
979
0
    }
980
0
  }
981
982
  /* RFC5280 (https://tools.ietf.org/html/rfc5280#section-7.1)
983
   * requires that the LDAP StringPrep profile and caseIgnoreMatch
984
   * must be used for this comparison. We do not use that but
985
   * instead we do a simpler comparison that ignores the tags used
986
   * such as `UTF8String` and `PrintableString`. */
987
988
0
  if ((dn1->size == 0) || (dn2->size == 0)) {
989
0
    gnutls_assert();
990
0
    return 0;
991
0
  }
992
993
0
  ret = gnutls_x509_rdn_get2(dn1, &str1, 0);
994
0
  if (ret < 0) {
995
0
    gnutls_assert();
996
0
    return 0;
997
0
  }
998
999
0
  ret = gnutls_x509_rdn_get2(dn2, &str2, 0);
1000
0
  if (ret < 0) {
1001
0
    gnutls_assert();
1002
0
    _gnutls_free_datum(&str1);
1003
0
    return 0;
1004
0
  }
1005
1006
0
  if (str1.size != str2.size) {
1007
0
    ret = 0;
1008
0
    goto cleanup;
1009
0
  }
1010
0
  if (memcmp(str1.data, str2.data, str2.size) != 0) {
1011
0
    gnutls_assert();
1012
0
    ret = 0;
1013
0
    goto cleanup;
1014
0
  }
1015
1016
0
  ret = 1;    /* they match */
1017
1018
0
 cleanup:
1019
0
  _gnutls_free_datum(&str1);
1020
0
  _gnutls_free_datum(&str2);
1021
1022
0
  return ret;
1023
0
}