aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/x509/x509.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/https/x509/x509.c')
-rw-r--r--src/daemon/https/x509/x509.c622
1 files changed, 0 insertions, 622 deletions
diff --git a/src/daemon/https/x509/x509.c b/src/daemon/https/x509/x509.c
index 8e3135c8..9ce1e76d 100644
--- a/src/daemon/https/x509/x509.c
+++ b/src/daemon/https/x509/x509.c
@@ -32,7 +32,6 @@
32#include <gnutls_x509.h> 32#include <gnutls_x509.h>
33#include <x509_b64.h> 33#include <x509_b64.h>
34#include <x509.h> 34#include <x509.h>
35#include <dn.h>
36#include <extensions.h> 35#include <extensions.h>
37#include <libtasn1.h> 36#include <libtasn1.h>
38#include <mpi.h> 37#include <mpi.h>
@@ -178,148 +177,6 @@ cleanup:MHD_gnutls_free (signature);
178} 177}
179 178
180/** 179/**
181 * MHD_gnutls_x509_crt_get_dn_by_oid - This function returns the Certificate's distinguished name
182 * @cert: should contain a MHD_gnutls_x509_crt_t structure
183 * @oid: holds an Object Identified in null terminated string
184 * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
185 * @raw_flag: If non zero returns the raw DER data of the DN part.
186 * @buf: a pointer where the DN part will be copied (may be null).
187 * @sizeof_buf: initially holds the size of @buf
188 *
189 * This function will extract the part of the name of the Certificate
190 * subject specified by the given OID. The output, if the raw flag is not
191 * used, will be encoded as described in RFC2253. Thus a string that is
192 * ASCII or UTF-8 encoded, depending on the certificate data.
193 *
194 * Some helper macros with popular OIDs can be found in gnutls/x509.h
195 * If raw flag is zero, this function will only return known OIDs as
196 * text. Other OIDs will be DER encoded, as described in RFC2253 --
197 * in hex format with a '\#' prefix. You can check about known OIDs
198 * using MHD_gnutls_x509_dn_oid_known().
199 *
200 * If @buf is null then only the size will be filled.
201 *
202 * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
203 * long enough, and in that case the *sizeof_buf will be updated with
204 * the required size. On success 0 is returned.
205 *
206 **/
207int
208MHD_gnutls_x509_crt_get_dn_by_oid (MHD_gnutls_x509_crt_t cert,
209 const char *oid,
210 int indx,
211 unsigned int raw_flag,
212 void *buf, size_t * sizeof_buf)
213{
214 if (cert == NULL)
215 {
216 MHD_gnutls_assert ();
217 return GNUTLS_E_INVALID_REQUEST;
218 }
219
220 return MHD__gnutls_x509_parse_dn_oid (cert->cert,
221 "tbsCertificate.subject.rdnSequence",
222 oid, indx, raw_flag, buf, sizeof_buf);
223}
224
225/**
226 * MHD_gnutls_x509_crt_get_signature_algorithm - This function returns the Certificate's signature algorithm
227 * @cert: should contain a MHD_gnutls_x509_crt_t structure
228 *
229 * This function will return a value of the MHD_gnutls_sign_algorithm_t enumeration that
230 * is the signature algorithm.
231 *
232 * Returns a negative value on error.
233 *
234 **/
235int
236MHD_gnutls_x509_crt_get_signature_algorithm (MHD_gnutls_x509_crt_t cert)
237{
238 int result;
239 MHD_gnutls_datum_t sa;
240
241 if (cert == NULL)
242 {
243 MHD_gnutls_assert ();
244 return GNUTLS_E_INVALID_REQUEST;
245 }
246
247 /* Read the signature algorithm. Note that parameters are not
248 * read. They will be read from the issuer's certificate if needed.
249 */
250 result =
251 MHD__gnutls_x509_read_value (cert->cert, "signatureAlgorithm.algorithm",
252 &sa, 0);
253
254 if (result < 0)
255 {
256 MHD_gnutls_assert ();
257 return result;
258 }
259
260 result = MHD_gtls_x509_oid2sign_algorithm ((const char *) sa.data);
261
262 MHD__gnutls_free_datum (&sa);
263
264 return result;
265}
266
267/**
268 * MHD_gnutls_x509_crt_get_signature - Returns the Certificate's signature
269 * @cert: should contain a MHD_gnutls_x509_crt_t structure
270 * @sig: a pointer where the signature part will be copied (may be null).
271 * @sizeof_sig: initially holds the size of @sig
272 *
273 * This function will extract the signature field of a certificate.
274 *
275 * Returns 0 on success, and a negative value on error.
276 **/
277int
278MHD_gnutls_x509_crt_get_signature (MHD_gnutls_x509_crt_t cert,
279 char *sig, size_t * sizeof_sig)
280{
281 int result;
282 int bits, len;
283
284 if (cert == NULL)
285 {
286 MHD_gnutls_assert ();
287 return GNUTLS_E_INVALID_REQUEST;
288 }
289
290 bits = 0;
291 result = MHD__asn1_read_value (cert->cert, "signature", NULL, &bits);
292 if (result != ASN1_MEM_ERROR)
293 {
294 MHD_gnutls_assert ();
295 return MHD_gtls_asn2err (result);
296 }
297
298 if (bits % 8 != 0)
299 {
300 MHD_gnutls_assert ();
301 return GNUTLS_E_CERTIFICATE_ERROR;
302 }
303
304 len = bits / 8;
305
306 if (*sizeof_sig < len)
307 {
308 *sizeof_sig = bits / 8;
309 return GNUTLS_E_SHORT_MEMORY_BUFFER;
310 }
311
312 result = MHD__asn1_read_value (cert->cert, "signature", sig, &len);
313 if (result != ASN1_SUCCESS)
314 {
315 MHD_gnutls_assert ();
316 return MHD_gtls_asn2err (result);
317 }
318
319 return 0;
320}
321
322/**
323 * MHD_gnutls_x509_crt_get_version - This function returns the Certificate's version number 180 * MHD_gnutls_x509_crt_get_version - This function returns the Certificate's version number
324 * @cert: should contain a MHD_gnutls_x509_crt_t structure 181 * @cert: should contain a MHD_gnutls_x509_crt_t structure
325 * 182 *
@@ -400,50 +257,6 @@ MHD_gnutls_x509_crt_get_expiration_time (MHD_gnutls_x509_crt_t cert)
400} 257}
401 258
402/** 259/**
403 * MHD_gnutls_x509_crt_get_serial - This function returns the certificate's serial number
404 * @cert: should contain a MHD_gnutls_x509_crt_t structure
405 * @result: The place where the serial number will be copied
406 * @result_size: Holds the size of the result field.
407 *
408 * This function will return the X.509 certificate's serial number.
409 * This is obtained by the X509 Certificate serialNumber
410 * field. Serial is not always a 32 or 64bit number. Some CAs use
411 * large serial numbers, thus it may be wise to handle it as something
412 * opaque.
413 *
414 * Returns 0 on success and a negative value in case of an error.
415 *
416 **/
417int
418MHD_gnutls_x509_crt_get_serial (MHD_gnutls_x509_crt_t cert,
419 void *result, size_t * result_size)
420{
421 int ret, len;
422
423 if (cert == NULL)
424 {
425 MHD_gnutls_assert ();
426 return GNUTLS_E_INVALID_REQUEST;
427 }
428
429 len = *result_size;
430 ret
431 =
432 MHD__asn1_read_value (cert->cert, "tbsCertificate.serialNumber", result,
433 &len);
434 *result_size = len;
435
436 if (ret != ASN1_SUCCESS)
437 {
438 MHD_gnutls_assert ();
439 return MHD_gtls_asn2err (ret);
440 }
441
442 return 0;
443}
444
445
446/**
447 * MHD_gnutls_x509_crt_get_pk_algorithm - This function returns the certificate's PublicKey algorithm 260 * MHD_gnutls_x509_crt_get_pk_algorithm - This function returns the certificate's PublicKey algorithm
448 * @cert: should contain a MHD_gnutls_x509_crt_t structure 261 * @cert: should contain a MHD_gnutls_x509_crt_t structure
449 * @bits: if bits is non null it will hold the size of the parameters' in bits 262 * @bits: if bits is non null it will hold the size of the parameters' in bits
@@ -496,396 +309,6 @@ is_type_printable (int type)
496 return 0; 309 return 0;
497} 310}
498 311
499#define XMPP_OID "1.3.6.1.5.5.7.8.5"
500
501/* returns the type and the name on success.
502 * Type is also returned as a parameter in case of an error.
503 */
504static int
505parse_general_name (ASN1_TYPE src,
506 const char *src_name,
507 int seq,
508 void *name,
509 size_t * name_size,
510 unsigned int *ret_type, int othername_oid)
511{
512 int len;
513 char nptr[MAX_NAME_SIZE];
514 int result;
515 opaque choice_type[128];
516 MHD_gnutls_x509_subject_alt_name_t type;
517
518 seq++; /* 0->1, 1->2 etc */
519
520 if (src_name[0] != 0)
521 snprintf (nptr, sizeof (nptr), "%s.?%u", src_name, seq);
522 else
523 snprintf (nptr, sizeof (nptr), "?%u", seq);
524
525 len = sizeof (choice_type);
526 result = MHD__asn1_read_value (src, nptr, choice_type, &len);
527
528 if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
529 {
530 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
531 }
532
533 if (result != ASN1_SUCCESS)
534 {
535 MHD_gnutls_assert ();
536 return MHD_gtls_asn2err (result);
537 }
538
539 type = MHD__gnutls_x509_san_find_type ((char *) choice_type);
540 if (type == (MHD_gnutls_x509_subject_alt_name_t) - 1)
541 {
542 MHD_gnutls_assert ();
543 return GNUTLS_E_X509_UNKNOWN_SAN;
544 }
545
546 if (ret_type)
547 *ret_type = type;
548
549 if (type == GNUTLS_SAN_OTHERNAME)
550 {
551 if (othername_oid)
552 MHD_gtls_str_cat (nptr, sizeof (nptr), ".otherName.type-id");
553 else
554 MHD_gtls_str_cat (nptr, sizeof (nptr), ".otherName.value");
555
556 len = *name_size;
557 result = MHD__asn1_read_value (src, nptr, name, &len);
558 *name_size = len;
559
560 if (result == ASN1_MEM_ERROR)
561 return GNUTLS_E_SHORT_MEMORY_BUFFER;
562
563 if (result != ASN1_SUCCESS)
564 {
565 MHD_gnutls_assert ();
566 return MHD_gtls_asn2err (result);
567 }
568
569 if (othername_oid)
570 {
571 if (len > strlen (XMPP_OID) && strcmp (name, XMPP_OID) == 0)
572 type = GNUTLS_SAN_OTHERNAME_XMPP;
573 }
574 else
575 {
576 char oid[42];
577
578 if (src_name[0] != 0)
579 snprintf (nptr, sizeof (nptr), "%s.?%u.otherName.type-id",
580 src_name, seq);
581 else
582 snprintf (nptr, sizeof (nptr), "?%u.otherName.type-id", seq);
583
584 len = sizeof (oid);
585 result = MHD__asn1_read_value (src, nptr, oid, &len);
586 if (result != ASN1_SUCCESS)
587 {
588 MHD_gnutls_assert ();
589 return MHD_gtls_asn2err (result);
590 }
591
592 if (len > strlen (XMPP_OID) && strcmp (oid, XMPP_OID) == 0)
593 {
594 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
595
596 result =
597 MHD__asn1_create_element (MHD__gnutls_get_pkix (),
598 "PKIX1.XmppAddr", &c2);
599 if (result != ASN1_SUCCESS)
600 {
601 MHD_gnutls_assert ();
602 return MHD_gtls_asn2err (result);
603 }
604
605 result = MHD__asn1_der_decoding (&c2, name, *name_size, NULL);
606 if (result != ASN1_SUCCESS)
607 {
608 MHD_gnutls_assert ();
609 MHD__asn1_delete_structure (&c2);
610 return MHD_gtls_asn2err (result);
611 }
612
613 result = MHD__asn1_read_value (c2, "", name, &len);
614 *name_size = len;
615 if (result != ASN1_SUCCESS)
616 {
617 MHD_gnutls_assert ();
618 MHD__asn1_delete_structure (&c2);
619 return MHD_gtls_asn2err (result);
620 }
621 MHD__asn1_delete_structure (&c2);
622 }
623 }
624 }
625 else if (type == GNUTLS_SAN_DN)
626 {
627 MHD_gtls_str_cat (nptr, sizeof (nptr), ".directoryName");
628 result = MHD__gnutls_x509_parse_dn (src, nptr, name, name_size);
629 if (result < 0)
630 {
631 MHD_gnutls_assert ();
632 return result;
633 }
634 }
635 else if (othername_oid)
636 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
637 else
638 {
639 size_t orig_name_size = *name_size;
640
641 MHD_gtls_str_cat (nptr, sizeof (nptr), ".");
642 MHD_gtls_str_cat (nptr, sizeof (nptr), (const char *) choice_type);
643
644 len = *name_size;
645 result = MHD__asn1_read_value (src, nptr, name, &len);
646 *name_size = len;
647
648 if (result == ASN1_MEM_ERROR)
649 {
650 if (is_type_printable (type))
651 (*name_size)++;
652 return GNUTLS_E_SHORT_MEMORY_BUFFER;
653 }
654
655 if (result != ASN1_SUCCESS)
656 {
657 MHD_gnutls_assert ();
658 return MHD_gtls_asn2err (result);
659 }
660
661 if (is_type_printable (type))
662 {
663
664 if (len + 1 > orig_name_size)
665 {
666 MHD_gnutls_assert ();
667 (*name_size)++;
668 return GNUTLS_E_SHORT_MEMORY_BUFFER;
669 }
670
671 /* null terminate it */
672 ((char *) name)[*name_size] = 0;
673 }
674
675 }
676
677 return type;
678}
679
680static int
681get_subject_alt_name (MHD_gnutls_x509_crt_t cert,
682 unsigned int seq,
683 void *ret,
684 size_t * ret_size,
685 unsigned int *ret_type,
686 unsigned int *critical, int othername_oid)
687{
688 int result;
689 MHD_gnutls_datum_t dnsname;
690 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
691 MHD_gnutls_x509_subject_alt_name_t type;
692
693 if (cert == NULL)
694 {
695 MHD_gnutls_assert ();
696 return GNUTLS_E_INVALID_REQUEST;
697 }
698
699 if (ret)
700 memset (ret, 0, *ret_size);
701 else
702 *ret_size = 0;
703
704 if ((result =
705 MHD__gnutls_x509_crt_get_extension (cert, "2.5.29.17", 0, &dnsname,
706 critical)) < 0)
707 {
708 return result;
709 }
710
711 if (dnsname.size == 0 || dnsname.data == NULL)
712 {
713 MHD_gnutls_assert ();
714 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
715 }
716
717 result =
718 MHD__asn1_create_element (MHD__gnutls_get_pkix (), "PKIX1.SubjectAltName",
719 &c2);
720 if (result != ASN1_SUCCESS)
721 {
722 MHD_gnutls_assert ();
723 MHD__gnutls_free_datum (&dnsname);
724 return MHD_gtls_asn2err (result);
725 }
726
727 result = MHD__asn1_der_decoding (&c2, dnsname.data, dnsname.size, NULL);
728 MHD__gnutls_free_datum (&dnsname);
729
730 if (result != ASN1_SUCCESS)
731 {
732 MHD_gnutls_assert ();
733 MHD__asn1_delete_structure (&c2);
734 return MHD_gtls_asn2err (result);
735 }
736
737 result = parse_general_name (c2, "", seq, ret, ret_size, ret_type,
738 othername_oid);
739
740 MHD__asn1_delete_structure (&c2);
741
742 if (result < 0)
743 {
744 return result;
745 }
746
747 type = result;
748
749 return type;
750}
751
752/**
753 * MHD_gnutls_x509_crt_get_subject_alt_name - Get certificate's alternative name, if any
754 * @cert: should contain a MHD_gnutls_x509_crt_t structure
755 * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.)
756 * @ret: is the place where the alternative name will be copied to
757 * @ret_size: holds the size of ret.
758 * @critical: will be non zero if the extension is marked as critical (may be null)
759 *
760 * This function will return the alternative names, contained in the
761 * given certificate.
762 *
763 * This is specified in X509v3 Certificate Extensions. GNUTLS will
764 * return the Alternative name (2.5.29.17), or a negative error code.
765 *
766 * When the SAN type is otherName, it will extract the data in the
767 * otherName's value field, and %GNUTLS_SAN_OTHERNAME is returned.
768 * You may use MHD_gnutls_x509_crt_get_subject_alt_othername_oid() to get
769 * the corresponding OID and the "virtual" SAN types (e.g.,
770 * %GNUTLS_SAN_OTHERNAME_XMPP).
771 *
772 * If an otherName OID is known, the data will be decoded. Otherwise
773 * the returned data will be DER encoded, and you will have to decode
774 * it yourself. Currently, only the RFC 3920 id-on-xmppAddr SAN is
775 * recognized.
776 *
777 * Returns the alternative subject name type on success. The type is
778 * one of the enumerated MHD_gnutls_x509_subject_alt_name_t. It will
779 * return %GNUTLS_E_SHORT_MEMORY_BUFFER if @ret_size is not large
780 * enough to hold the value. In that case @ret_size will be updated
781 * with the required size. If the certificate does not have an
782 * Alternative name with the specified sequence number then
783 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
784 *
785 **/
786int
787MHD_gnutls_x509_crt_get_subject_alt_name (MHD_gnutls_x509_crt_t cert,
788 unsigned int seq,
789 void *ret,
790 size_t * ret_size,
791 unsigned int *critical)
792{
793 return get_subject_alt_name (cert, seq, ret, ret_size, NULL, critical, 0);
794}
795
796/**
797 * MHD_gnutls_x509_crt_get_basic_constraints - This function returns the certificate basic constraints
798 * @cert: should contain a MHD_gnutls_x509_crt_t structure
799 * @critical: will be non zero if the extension is marked as critical
800 * @ca: pointer to output integer indicating CA status, may be NULL,
801 * value is 1 if the certificate CA flag is set, 0 otherwise.
802 * @pathlen: pointer to output integer indicating path length (may be
803 * NULL), non-negative values indicate a present pathLenConstraint
804 * field and the actual value, -1 indicate that the field is absent.
805 *
806 * This function will read the certificate's basic constraints, and
807 * return the certificates CA status. It reads the basicConstraints
808 * X.509 extension (2.5.29.19).
809 *
810 * Return value: If the certificate is a CA a positive value will be
811 * returned, or zero if the certificate does not have CA flag set. A
812 * negative value may be returned in case of errors. If the
813 * certificate does not contain the basicConstraints extension
814 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
815 **/
816static int
817MHD_gnutls_x509_crt_get_basic_constraints (MHD_gnutls_x509_crt_t cert,
818 unsigned int *critical,
819 int *ca, int *pathlen)
820{
821 int result;
822 MHD_gnutls_datum_t basicConstraints;
823 int tmp_ca;
824
825 if (cert == NULL)
826 {
827 MHD_gnutls_assert ();
828 return GNUTLS_E_INVALID_REQUEST;
829 }
830
831 if ((result = MHD__gnutls_x509_crt_get_extension (cert, "2.5.29.19", 0,
832 &basicConstraints,
833 critical)) < 0)
834 {
835 return result;
836 }
837
838 if (basicConstraints.size == 0 || basicConstraints.data == NULL)
839 {
840 MHD_gnutls_assert ();
841 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
842 }
843
844 result = MHD__gnutls_x509_ext_extract_basicConstraints (&tmp_ca, pathlen,
845 basicConstraints.
846 data,
847 basicConstraints.
848 size);
849 if (ca)
850 *ca = tmp_ca;
851 MHD__gnutls_free_datum (&basicConstraints);
852
853 if (result < 0)
854 {
855 MHD_gnutls_assert ();
856 return result;
857 }
858
859 return tmp_ca;
860}
861
862/**
863 * MHD_gnutls_x509_crt_get_ca_status - This function returns the certificate CA status
864 * @cert: should contain a MHD_gnutls_x509_crt_t structure
865 * @critical: will be non zero if the extension is marked as critical
866 *
867 * This function will return certificates CA status, by reading the
868 * basicConstraints X.509 extension (2.5.29.19). If the certificate is
869 * a CA a positive value will be returned, or zero if the certificate
870 * does not have CA flag set.
871 *
872 * Use MHD_gnutls_x509_crt_get_basic_constraints() if you want to read the
873 * pathLenConstraint field too.
874 *
875 * A negative value may be returned in case of parsing error.
876 * If the certificate does not contain the basicConstraints extension
877 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
878 *
879 **/
880int
881MHD_gnutls_x509_crt_get_ca_status (MHD_gnutls_x509_crt_t cert,
882 unsigned int *critical)
883{
884 int ca, pathlen;
885 return MHD_gnutls_x509_crt_get_basic_constraints (cert, critical, &ca,
886 &pathlen);
887}
888
889/** 312/**
890 * MHD_gnutls_x509_crt_get_key_usage - This function returns the certificate's key usage 313 * MHD_gnutls_x509_crt_get_key_usage - This function returns the certificate's key usage
891 * @cert: should contain a MHD_gnutls_x509_crt_t structure 314 * @cert: should contain a MHD_gnutls_x509_crt_t structure
@@ -1013,24 +436,6 @@ cleanup:MHD__asn1_delete_structure (&c2);
1013} 436}
1014 437
1015/** 438/**
1016 * MHD_gnutls_x509_crt_get_raw_issuer_dn - This function returns the issuer's DN DER encoded
1017 * @cert: should contain a MHD_gnutls_x509_crt_t structure
1018 * @start: will hold the starting point of the DN
1019 *
1020 * This function will return a pointer to the DER encoded DN structure
1021 * and the length.
1022 *
1023 * Returns 0 on success or a negative value on error.
1024 *
1025 **/
1026int
1027MHD_gnutls_x509_crt_get_raw_issuer_dn (MHD_gnutls_x509_crt_t cert,
1028 MHD_gnutls_datum_t * start)
1029{
1030 return MHD__gnutls_x509_crt_get_raw_dn2 (cert, "issuer", start);
1031}
1032
1033/**
1034 * MHD_gnutls_x509_crt_get_raw_dn - This function returns the subject's DN DER encoded 439 * MHD_gnutls_x509_crt_get_raw_dn - This function returns the subject's DN DER encoded
1035 * @cert: should contain a MHD_gnutls_x509_crt_t structure 440 * @cert: should contain a MHD_gnutls_x509_crt_t structure
1036 * @start: will hold the starting point of the DN 441 * @start: will hold the starting point of the DN
@@ -1048,33 +453,6 @@ MHD_gnutls_x509_crt_get_raw_dn (MHD_gnutls_x509_crt_t cert,
1048 return MHD__gnutls_x509_crt_get_raw_dn2 (cert, "subject", start); 453 return MHD__gnutls_x509_crt_get_raw_dn2 (cert, "subject", start);
1049} 454}
1050 455
1051static int
1052get_dn (MHD_gnutls_x509_crt_t cert, const char *whom,
1053 MHD_gnutls_x509_dn_t * dn)
1054{
1055 *dn = MHD__asn1_find_node (cert->cert, whom);
1056 if (!*dn)
1057 return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
1058 return 0;
1059}
1060
1061/**
1062 * MHD_gnutls_x509_crt_get_subject: get opaque subject DN pointer
1063 * @cert: should contain a MHD_gnutls_x509_crt_t structure
1064 * @dn: output variable with pointer to opaque DN.
1065 *
1066 * Return the Certificate's Subject DN as an opaque data type. You
1067 * may use MHD_gnutls_x509_dn_get_rdn_ava() to decode the DN.
1068 *
1069 * Returns: Returns 0 on success, or an error code.
1070 **/
1071int
1072MHD_gnutls_x509_crt_get_subject (MHD_gnutls_x509_crt_t cert,
1073 MHD_gnutls_x509_dn_t * dn)
1074{
1075 return get_dn (cert, "tbsCertificate.subject.rdnSequence", dn);
1076}
1077
1078/** 456/**
1079 * MHD_gnutls_x509_crt_export - This function will export the certificate 457 * MHD_gnutls_x509_crt_export - This function will export the certificate
1080 * @cert: Holds the certificate 458 * @cert: Holds the certificate