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