]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Introduced new functions to allow multiple DN parsing modes
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 11 Nov 2016 15:20:01 +0000 (16:20 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 14 Nov 2016 12:34:51 +0000 (13:34 +0100)
The old DN parsing functions are changed to return the original
non-fully compliant with RFC4514 string format, while the new
ones return the compliant string by default. This allows applications
which relied on the previous format to continue functioning without
changes.

lib/includes/gnutls/ocsp.h
lib/includes/gnutls/x509.h
lib/libgnutls.map
lib/x509/crl.c
lib/x509/crq.c
lib/x509/dn.c
lib/x509/ocsp.c
lib/x509/x509.c
lib/x509/x509_dn.c
lib/x509/x509_int.h

index 1a96ce8a2978898158bb309337b2a4e578fe92b2..8ade965dc0e52c80c16db890e7b87cd0db2e4b08 100644 (file)
@@ -211,6 +211,9 @@ int gnutls_ocsp_resp_get_response(gnutls_ocsp_resp_t resp,
 int gnutls_ocsp_resp_get_version(gnutls_ocsp_resp_t resp);
 int gnutls_ocsp_resp_get_responder(gnutls_ocsp_resp_t resp,
                                   gnutls_datum_t * dn);
+int gnutls_ocsp_resp_get_responder2(gnutls_ocsp_resp_t resp,
+                                   gnutls_datum_t * dn,
+                                   unsigned flags);
 
 /* the raw key ID of the responder */
 #define GNUTLS_OCSP_RESP_ID_KEY 1
index f665c34eb20d1d619f8176fb0f5bb5e980af7645..249b22bb4fd56e7d76561705120180f5d42c4872 100644 (file)
@@ -171,6 +171,8 @@ int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt_t cert,
                                  char *buf, size_t * buf_size);
 int gnutls_x509_crt_get_issuer_dn2(gnutls_x509_crt_t cert,
                                   gnutls_datum_t * dn);
+int gnutls_x509_crt_get_issuer_dn3(gnutls_x509_crt_t cert,
+                                  gnutls_datum_t * dn, unsigned flags);
 int gnutls_x509_crt_get_issuer_dn_oid(gnutls_x509_crt_t cert,
                                      unsigned indx, void *oid,
                                      size_t * oid_size);
@@ -178,9 +180,12 @@ int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt_t cert,
                                         const char *oid, unsigned indx,
                                         unsigned int raw_flag,
                                         void *buf, size_t * buf_size);
+
 int gnutls_x509_crt_get_dn(gnutls_x509_crt_t cert, char *buf,
                           size_t * buf_size);
 int gnutls_x509_crt_get_dn2(gnutls_x509_crt_t cert, gnutls_datum_t * dn);
+int gnutls_x509_crt_get_dn3(gnutls_x509_crt_t cert, gnutls_datum_t * dn, unsigned flags);
+
 int gnutls_x509_crt_get_dn_oid(gnutls_x509_crt_t cert, unsigned indx,
                               void *oid, size_t * oid_size);
 int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt_t cert,
@@ -663,6 +668,10 @@ int gnutls_x509_crt_get_raw_dn(gnutls_x509_crt_t cert,
  */
 int gnutls_x509_rdn_get(const gnutls_datum_t * idn,
                        char *buf, size_t * sizeof_buf);
+int
+gnutls_x509_rdn_get2(const gnutls_datum_t * idn,
+                     gnutls_datum_t *str, unsigned flags);
+
 int gnutls_x509_rdn_get_oid(const gnutls_datum_t * idn,
                            unsigned indx, void *buf, size_t * sizeof_buf);
 
@@ -687,6 +696,10 @@ int gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn, int irdn,
                               int iava, gnutls_x509_ava_st * ava);
 
 int gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str);
+
+#define GNUTLS_X509_DN_FLAG_COMPAT 1
+int gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str, unsigned flags);
+
 int
 gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str, const char **err);
 
@@ -728,6 +741,9 @@ int gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl_t crl,
                                  char *buf, size_t * sizeof_buf);
 int gnutls_x509_crl_get_issuer_dn2(gnutls_x509_crl_t crl,
                                   gnutls_datum_t * dn);
+int gnutls_x509_crl_get_issuer_dn3(gnutls_x509_crl_t crl,
+                                  gnutls_datum_t * dn, unsigned flags);
+
 int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl_t crl,
                                         const char *oid, unsigned indx,
                                         unsigned int raw_flag,
@@ -1231,6 +1247,7 @@ int gnutls_x509_crq_get_private_key_usage_period(gnutls_x509_crq_t
 int gnutls_x509_crq_get_dn(gnutls_x509_crq_t crq, char *buf,
                           size_t * sizeof_buf);
 int gnutls_x509_crq_get_dn2(gnutls_x509_crq_t crq, gnutls_datum_t * dn);
+int gnutls_x509_crq_get_dn3(gnutls_x509_crq_t crq, gnutls_datum_t * dn, unsigned flags);
 int gnutls_x509_crq_get_dn_oid(gnutls_x509_crq_t crq, unsigned indx,
                               void *oid, size_t * sizeof_oid);
 int gnutls_x509_crq_get_dn_by_oid(gnutls_x509_crq_t crq,
index c0186f5524ec46d1ab4b9539c2024e5ab8790876..9b947baac6338bfef3579d7700647357e3050711 100644 (file)
@@ -1124,6 +1124,13 @@ GNUTLS_3_4
        gnutls_anon_set_server_known_dh_params;
        gnutls_psk_set_server_known_dh_params;
        gnutls_x509_crt_check_key_purpose;
+       gnutls_ocsp_resp_get_responder2;
+       gnutls_x509_crt_get_issuer_dn3;
+       gnutls_x509_crt_get_dn3;
+       gnutls_x509_rdn_get2;
+       gnutls_x509_dn_get_str2;
+       gnutls_x509_crl_get_issuer_dn3;
+       gnutls_x509_crq_get_dn3;
  local:
        *;
 };
index 5f0abe301e47bc4ee3e836dfdb2c6d957b64c78e..036703a1bc63dfc8925795426eb1aa4f05f9d3fe 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2003-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2016 Red Hat, Inc.
  *
  * Author: Nikos Mavrogiannopoulos
  *
@@ -194,6 +195,9 @@ gnutls_x509_crl_import(gnutls_x509_crl_t crl,
  *
  * If buf is %NULL then only the size will be filled.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crl_get_issuer_dn3().
+ *
  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
  * not long enough, and in that case the sizeof_buf will be updated
  * with the required size, and 0 on success.
@@ -210,7 +214,7 @@ gnutls_x509_crl_get_issuer_dn(const gnutls_x509_crl_t crl, char *buf,
 
        return _gnutls_x509_parse_dn(crl->crl,
                                     "tbsCertList.issuer.rdnSequence",
-                                    buf, sizeof_buf);
+                                    buf, sizeof_buf, GNUTLS_X509_DN_FLAG_COMPAT);
 }
 
 /**
@@ -303,6 +307,9 @@ gnutls_x509_crl_get_dn_oid(gnutls_x509_crl_t crl,
  * described in RFC4514. The output string will be ASCII or UTF-8
  * encoded, depending on the certificate data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crl_get_issuer_dn3().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
@@ -317,7 +324,41 @@ gnutls_x509_crl_get_issuer_dn2(gnutls_x509_crl_t crl, gnutls_datum_t * dn)
        }
 
        return _gnutls_x509_get_dn(crl->crl,
-                                  "tbsCertList.issuer.rdnSequence", dn);
+                                  "tbsCertList.issuer.rdnSequence",
+                                  dn, GNUTLS_X509_DN_FLAG_COMPAT);
+}
+
+/**
+ * gnutls_x509_crl_get_issuer_dn3:
+ * @crl: should contain a #gnutls_x509_crl_t type
+ * @dn: a pointer to a structure to hold the name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will allocate buffer and copy the name of the CRL issuer.
+ * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
+ * described in RFC4514. The output string will be ASCII or UTF-8
+ * encoded, depending on the certificate data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.5.7
+ **/
+int
+gnutls_x509_crl_get_issuer_dn3(gnutls_x509_crl_t crl, gnutls_datum_t * dn, unsigned flags)
+{
+       if (crl == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return _gnutls_x509_get_dn(crl->crl,
+                                  "tbsCertList.issuer.rdnSequence",
+                                  dn, flags);
 }
 
 /**
index 6a9cccaa5ef6448561e490af07c9eddba189e2ed..50c3e632f1d258b611a904b7ced2f8723b0320ce 100644 (file)
@@ -255,6 +255,9 @@ gnutls_x509_crq_get_private_key_usage_period(gnutls_x509_crq_t crq,
  * @buf will be ASCII or UTF-8 encoded, depending on the certificate
  * data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crq_get_dn3().
+ *
  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
  *   long enough, and in that case the *@buf_size will be updated with
  *   the required size.  On success 0 is returned.
@@ -269,7 +272,7 @@ gnutls_x509_crq_get_dn(gnutls_x509_crq_t crq, char *buf, size_t * buf_size)
 
        return _gnutls_x509_parse_dn(crq->crq,
                                     "certificationRequestInfo.subject.rdnSequence",
-                                    buf, buf_size);
+                                    buf, buf_size, GNUTLS_X509_DN_FLAG_COMPAT);
 }
 
 /**
@@ -282,6 +285,9 @@ gnutls_x509_crq_get_dn(gnutls_x509_crq_t crq, char *buf, size_t * buf_size)
  * described in RFC4514. The output string will be ASCII or UTF-8
  * encoded, depending on the certificate data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crq_get_dn3().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value. and a negative error code on error.
  *
@@ -296,7 +302,39 @@ int gnutls_x509_crq_get_dn2(gnutls_x509_crq_t crq, gnutls_datum_t * dn)
 
        return _gnutls_x509_get_dn(crq->crq,
                                   "certificationRequestInfo.subject.rdnSequence",
-                                  dn);
+                                  dn, GNUTLS_X509_DN_FLAG_COMPAT);
+}
+
+/**
+ * gnutls_x509_crq_get_dn3:
+ * @crq: should contain a #gnutls_x509_crq_t type
+ * @dn: a pointer to a structure to hold the name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will allocate buffer and copy the name of the Certificate 
+ * request. The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
+ * described in RFC4514. The output string will be ASCII or UTF-8
+ * encoded, depending on the certificate data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value. and a negative error code on error.
+ *
+ * Since: 3.5.7
+ **/
+int gnutls_x509_crq_get_dn3(gnutls_x509_crq_t crq, gnutls_datum_t * dn, unsigned flags)
+{
+       if (crq == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return _gnutls_x509_get_dn(crq->crq,
+                                  "certificationRequestInfo.subject.rdnSequence",
+                                  dn, flags);
 }
 
 /**
index 7209cdb92f661470c0b9bbe184355af46e7dc497..3395941403ce41e48f1db140787d221505c186e0 100644 (file)
  * Name (you need a parser just to read a name in the X.509 protocols!!!)
  */
 
-int
-_gnutls_x509_get_dn(ASN1_TYPE asn1_struct,
-                   const char *asn1_rdn_name, gnutls_datum_t * dn)
+static int append_elements(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_buffer_st *str, int k1, unsigned last)
 {
-       gnutls_buffer_st out_str;
-       int k2, k1, result, max_k2;
+       int k2, result, max_k2;
+       int len;
+       uint8_t value[MAX_STRING_LEN];
        char tmpbuffer1[ASN1_MAX_NAME_SIZE];
        char tmpbuffer2[ASN1_MAX_NAME_SIZE];
        char tmpbuffer3[ASN1_MAX_NAME_SIZE];
-       uint8_t value[MAX_STRING_LEN];
-       gnutls_datum_t td = { NULL, 0 }, tvd = {
-       NULL, 0};
        const char *ldap_desc;
        char oid[MAX_OID_SIZE];
-       int len;
+       gnutls_datum_t td = { NULL, 0 };
+       gnutls_datum_t tvd = { NULL, 0 };
 
-       _gnutls_buffer_init(&out_str);
+       /* create a string like "tbsCertList.issuer.rdnSequence.?1"
+        */
+       if (asn1_rdn_name[0] != 0)
+               snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
+                        asn1_rdn_name, k1);
+       else
+               snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
+                        k1);
 
-       result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1);
-       if (result != ASN1_SUCCESS) {
+       len = sizeof(value) - 1;
+       result =
+           asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
+
+       if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
                gnutls_assert();
                result = _gnutls_asn2err(result);
                goto cleanup;
        }
 
-       if (k1 == 0) {
+       k2 = 0;
+
+       result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2);
+       if (result != ASN1_SUCCESS) {
                gnutls_assert();
-               result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+               result = _gnutls_asn2err(result);
                goto cleanup;
        }
 
-       while (k1 > 0) {
-               /* create a string like "tbsCertList.issuer.rdnSequence.?1"
-                */
-               if (asn1_rdn_name[0] != 0)
-                       snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u",
-                                asn1_rdn_name, k1);
+       do {            /* Move to the attibute type and values
+                                */
+               k2++;
+
+               if (tmpbuffer1[0] != 0)
+                       snprintf(tmpbuffer2, sizeof(tmpbuffer2),
+                                "%s.?%u", tmpbuffer1, k2);
                else
-                       snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u",
-                                k1);
-               k1--;
+                       snprintf(tmpbuffer2, sizeof(tmpbuffer2),
+                                "?%u", k2);
+
+               /* Try to read the RelativeDistinguishedName attributes.
+                */
 
                len = sizeof(value) - 1;
                result =
-                   asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
+                   asn1_read_value(asn1_struct, tmpbuffer2, value,
+                                   &len);
 
+               if (result == ASN1_ELEMENT_NOT_FOUND)
+                       break;
                if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
                        gnutls_assert();
                        result = _gnutls_asn2err(result);
                        goto cleanup;
                }
 
-               k2 = 0;
+               /* Read the OID 
+                */
+               _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
+                               tmpbuffer2);
+               _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
+                               ".type");
+
+               len = sizeof(oid) - 1;
+               result =
+                   asn1_read_value(asn1_struct, tmpbuffer3, oid,
+                                   &len);
 
-               result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2);
-               if (result != ASN1_SUCCESS) {
+               if (result == ASN1_ELEMENT_NOT_FOUND)
+                       break;
+               else if (result != ASN1_SUCCESS) {
                        gnutls_assert();
                        result = _gnutls_asn2err(result);
                        goto cleanup;
                }
 
-               do {            /* Move to the attibute type and values
-                                */
-                       k2++;
-
-                       if (tmpbuffer1[0] != 0)
-                               snprintf(tmpbuffer2, sizeof(tmpbuffer2),
-                                        "%s.?%u", tmpbuffer1, k2);
-                       else
-                               snprintf(tmpbuffer2, sizeof(tmpbuffer2),
-                                        "?%u", k2);
+               /* Read the Value 
+                */
+               _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
+                               tmpbuffer2);
+               _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
+                               ".value");
 
-                       /* Try to read the RelativeDistinguishedName attributes.
-                        */
+               len = 0;
 
-                       len = sizeof(value) - 1;
-                       result =
-                           asn1_read_value(asn1_struct, tmpbuffer2, value,
-                                           &len);
+               result =
+                   _gnutls_x509_read_value(asn1_struct,
+                                           tmpbuffer3, &tvd);
+               if (result < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \
+       gnutls_assert(); \
+       goto cleanup; \
+}
+#define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \
+       gnutls_assert(); \
+       goto cleanup; \
+}
+               /*   The encodings of adjoining RelativeDistinguishedNames are separated
+                *   by a comma character (',' ASCII 44).
+                */
 
-                       if (result == ASN1_ELEMENT_NOT_FOUND)
-                               break;
-                       if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */
-                               gnutls_assert();
-                               result = _gnutls_asn2err(result);
-                               goto cleanup;
-                       }
+               ldap_desc =
+                   gnutls_x509_dn_oid_name(oid,
+                                           GNUTLS_X509_DN_OID_RETURN_OID);
 
-                       /* Read the OID 
-                        */
-                       _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
-                                       tmpbuffer2);
-                       _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
-                                       ".type");
+               STR_APPEND(ldap_desc);
+               STR_APPEND("=");
 
-                       len = sizeof(oid) - 1;
-                       result =
-                           asn1_read_value(asn1_struct, tmpbuffer3, oid,
-                                           &len);
+               result =
+                   _gnutls_x509_dn_to_string(oid, tvd.data,
+                                             tvd.size, &td);
+               if (result < 0) {
+                       gnutls_assert();
+                       _gnutls_debug_log
+                           ("Cannot parse OID: '%s' with value '%s'\n",
+                            oid, _gnutls_bin2hex(tvd.data,
+                                                 tvd.size,
+                                                 tmpbuffer3,
+                                                 sizeof
+                                                 (tmpbuffer3),
+                                                 NULL));
+                       goto cleanup;
+               }
 
-                       if (result == ASN1_ELEMENT_NOT_FOUND)
-                               break;
-                       else if (result != ASN1_SUCCESS) {
-                               gnutls_assert();
-                               result = _gnutls_asn2err(result);
-                               goto cleanup;
-                       }
+               DATA_APPEND(td.data, td.size);
+               _gnutls_free_datum(&td);
+               _gnutls_free_datum(&tvd);
 
-                       /* Read the Value 
-                        */
-                       _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
-                                       tmpbuffer2);
-                       _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
-                                       ".value");
+               /*   Where there is a multi-valued RDN, the outputs from adjoining
+                *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
+                *   character.
+                */
+               if (k2 < max_k2) {
+                       STR_APPEND("+");
+               } else if (!last) {
+                       STR_APPEND(",");
+               }
+       }
+       while (1);
 
-                       len = 0;
+       result = 0;
 
-                       result =
-                           _gnutls_x509_read_value(asn1_struct,
-                                                   tmpbuffer3, &tvd);
-                       if (result < 0) {
-                               gnutls_assert();
-                               goto cleanup;
-                       }
-#define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \
-       gnutls_assert(); \
-       goto cleanup; \
-}
-#define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \
-       gnutls_assert(); \
-       goto cleanup; \
+ cleanup:
+       _gnutls_free_datum(&td);
+       _gnutls_free_datum(&tvd);
+       return result;
 }
-                       /*   The encodings of adjoining RelativeDistinguishedNames are separated
-                        *   by a comma character (',' ASCII 44).
-                        */
 
-                       ldap_desc =
-                           gnutls_x509_dn_oid_name(oid,
-                                                   GNUTLS_X509_DN_OID_RETURN_OID);
+int
+_gnutls_x509_get_dn(ASN1_TYPE asn1_struct,
+                   const char *asn1_rdn_name, gnutls_datum_t * dn,
+                   unsigned flags)
+{
+       gnutls_buffer_st out_str;
+       int i, k1, result;
 
-                       STR_APPEND(ldap_desc);
-                       STR_APPEND("=");
+       _gnutls_buffer_init(&out_str);
 
-                       result =
-                           _gnutls_x509_dn_to_string(oid, tvd.data,
-                                                     tvd.size, &td);
+       result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1);
+       if (result != ASN1_SUCCESS) {
+               gnutls_assert();
+               result = _gnutls_asn2err(result);
+               goto cleanup;
+       }
+
+       if (k1 == 0) {
+               gnutls_assert();
+               result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+               goto cleanup;
+       }
+
+       if (flags & GNUTLS_X509_DN_FLAG_COMPAT) {
+               for (i=0;i<k1;i++) {
+                       result = append_elements(asn1_struct, asn1_rdn_name, &out_str, i+1, (i==(k1-1))?1:0);
                        if (result < 0) {
                                gnutls_assert();
-                               _gnutls_debug_log
-                                   ("Cannot parse OID: '%s' with value '%s'\n",
-                                    oid, _gnutls_bin2hex(tvd.data,
-                                                         tvd.size,
-                                                         tmpbuffer3,
-                                                         sizeof
-                                                         (tmpbuffer3),
-                                                         NULL));
                                goto cleanup;
                        }
-
-                       DATA_APPEND(td.data, td.size);
-                       _gnutls_free_datum(&td);
-                       _gnutls_free_datum(&tvd);
-
-                       /*   Where there is a multi-valued RDN, the outputs from adjoining
-                        *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
-                        *   character.
-                        */
-                       if (k2 < max_k2) {
-                               STR_APPEND("+");
-                       } else if (k1 > 0) {
-                               STR_APPEND(",");
+               }
+       } else {
+               while (k1 > 0) {
+                       result = append_elements(asn1_struct, asn1_rdn_name, &out_str, k1, k1==1?1:0);
+                       if (result < 0) {
+                               gnutls_assert();
+                               goto cleanup;
                        }
-
+                       k1--;
                }
-               while (1);
        }
 
-       result = _gnutls_buffer_to_datum(&out_str, dn, 1);
-       if (result < 0)
-               gnutls_assert();
-
-       goto cleanup1;
+       return _gnutls_buffer_to_datum(&out_str, dn, 1);
 
     cleanup:
+ cleanup:
        _gnutls_buffer_clear(&out_str);
-      cleanup1:
-       _gnutls_free_datum(&td);
-       _gnutls_free_datum(&tvd);
        return result;
 
 }
@@ -235,7 +256,7 @@ _gnutls_x509_get_dn(ASN1_TYPE asn1_struct,
 int
 _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
                      const char *asn1_rdn_name, char *buf,
-                     size_t * buf_size)
+                     size_t * buf_size, unsigned flags)
 {
        int ret;
        gnutls_datum_t dn = {NULL, 0};
@@ -250,7 +271,7 @@ _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
        else
                *buf_size = 0;
 
-       ret = _gnutls_x509_get_dn(asn1_struct, asn1_rdn_name, &dn);
+       ret = _gnutls_x509_get_dn(asn1_struct, asn1_rdn_name, &dn, flags);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -760,6 +781,9 @@ _gnutls_x509_set_dn_oid(ASN1_TYPE asn1_struct,
  * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
  * RFC4514.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_rdn_get2().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
  * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
  * updated if the provided buffer is not long enough, otherwise a
@@ -796,7 +820,56 @@ gnutls_x509_rdn_get(const gnutls_datum_t * idn,
                return _gnutls_asn2err(result);
        }
 
-       result = _gnutls_x509_parse_dn(dn, "rdnSequence", buf, buf_size);
+       result = _gnutls_x509_parse_dn(dn, "rdnSequence", buf, buf_size, GNUTLS_X509_DN_FLAG_COMPAT);
+
+       asn1_delete_structure(&dn);
+       return result;
+
+}
+
+/**
+ * gnutls_x509_rdn_get2:
+ * @idn: should contain a DER encoded RDN sequence
+ * @buf: a pointer to a structure to hold the peer's name
+ * @buf_size: holds the size of @buf
+ * @flags: 
+ *
+ * This function will return the name of the given RDN sequence.  The
+ * name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in
+ * RFC4514.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or
+ * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned and *@buf_size is
+ * updated if the provided buffer is not long enough, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_rdn_get2(const gnutls_datum_t * idn,
+                    gnutls_datum_t *str, unsigned flags)
+{
+       int result;
+       ASN1_TYPE dn = ASN1_TYPE_EMPTY;
+
+       if ((result =
+            asn1_create_element(_gnutls_get_pkix(),
+                                "PKIX1.Name", &dn)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(result);
+       }
+
+       result = _asn1_strict_der_decode(&dn, idn->data, idn->size, NULL);
+       if (result != ASN1_SUCCESS) {
+               /* couldn't decode DER */
+               gnutls_assert();
+               asn1_delete_structure(&dn);
+               return _gnutls_asn2err(result);
+       }
+
+       result = _gnutls_x509_get_dn(dn, "rdnSequence", str, flags);
 
        asn1_delete_structure(&dn);
        return result;
index eb41fcb295bb779e00de9a169985a9698981866b..92f037029d3a3d1c4cc3cc53dc8fe24b6aa5686d 100644 (file)
@@ -1103,16 +1103,58 @@ int gnutls_ocsp_resp_get_version(gnutls_ocsp_resp_t resp)
  * The caller needs to deallocate memory by calling gnutls_free() on
  * @dn->data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_ocsp_resp_get_responder2().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
- *   negative error code is returned.
+ *   negative error code is returned. When no data exist it will
+ *   return success and set @dn elements to zero.
  **/
 int
 gnutls_ocsp_resp_get_responder(gnutls_ocsp_resp_t resp,
                               gnutls_datum_t * dn)
 {
        int ret;
-       size_t l = 0;
 
+       ret = gnutls_ocsp_resp_get_responder2(resp, dn, GNUTLS_X509_DN_FLAG_COMPAT);
+       if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+               dn->data = NULL;
+               dn->size = 0;
+               return 0; /* for backwards compatibility */
+       }
+
+       return ret;
+}
+
+/**
+ * gnutls_ocsp_resp_get_responder2:
+ * @resp: should contain a #gnutls_ocsp_resp_t type
+ * @dn: newly allocated buffer with name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will extract the name of the Basic OCSP Response in
+ * the provided buffer. The name will be in the form
+ * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string
+ * will be ASCII or UTF-8 encoded, depending on the certificate data.
+ *
+ * If the responder ID is not a name but a hash, this function
+ * will return zero and the @dn elements will be set to %NULL.
+ *
+ * The caller needs to deallocate memory by calling gnutls_free() on
+ * @dn->data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error code is returned. When no data exist it will return
+ *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
+ **/
+int
+gnutls_ocsp_resp_get_responder2(gnutls_ocsp_resp_t resp,
+                               gnutls_datum_t * dn, unsigned flags)
+{
        if (resp == NULL || dn == NULL) {
                gnutls_assert();
                return GNUTLS_E_INVALID_REQUEST;
@@ -1121,33 +1163,9 @@ gnutls_ocsp_resp_get_responder(gnutls_ocsp_resp_t resp,
        dn->data = NULL;
        dn->size = 0;
 
-       ret = _gnutls_x509_parse_dn
-           (resp->basicresp, "tbsResponseData.responderID.byName",
-            NULL, &l);
-       if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
-               if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-                       return 0; /* for backwards compatibility */
-               gnutls_assert();
-               return ret;
-       }
-
-       dn->data = gnutls_malloc(l);
-       if (dn->data == NULL) {
-               gnutls_assert();
-               return GNUTLS_E_MEMORY_ERROR;
-       }
-
-       ret = _gnutls_x509_parse_dn
-           (resp->basicresp, "tbsResponseData.responderID.byName",
-            (char *) dn->data, &l);
-       if (ret != GNUTLS_E_SUCCESS) {
-               gnutls_assert();
-               return ret;
-       }
-
-       dn->size = l;
-
-       return GNUTLS_E_SUCCESS;
+       return _gnutls_x509_get_dn(resp->basicresp,
+                                 "tbsResponseData.responderID.byName",
+                                 dn, flags);
 }
 
 /**
index a9adff2f4a3849495f45f54d7de65ebc198a348b..043d38b479b9ff971fac048e74b590e268907b02 100644 (file)
@@ -482,6 +482,9 @@ gnutls_x509_crt_import(gnutls_x509_crt_t cert,
  *
  * If @buf is null then only the size will be filled. 
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crt_get_issuer_dn3().
+ *
  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
  *   long enough, and in that case the @buf_size will be updated
  *   with the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if
@@ -498,7 +501,7 @@ gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt_t cert, char *buf,
 
        return _gnutls_x509_parse_dn(cert->cert,
                                     "tbsCertificate.issuer.rdnSequence",
-                                    buf, buf_size);
+                                    buf, buf_size, GNUTLS_X509_DN_FLAG_COMPAT);
 }
 
 /**
@@ -511,6 +514,9 @@ gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt_t cert, char *buf,
  * described in RFC4514. The output string will be ASCII or UTF-8
  * encoded, depending on the certificate data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crt_get_issuer_dn3().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
@@ -526,7 +532,40 @@ gnutls_x509_crt_get_issuer_dn2(gnutls_x509_crt_t cert, gnutls_datum_t * dn)
 
        return _gnutls_x509_get_dn(cert->cert,
                                   "tbsCertificate.issuer.rdnSequence",
-                                  dn);
+                                  dn, GNUTLS_X509_DN_FLAG_COMPAT);
+}
+
+/**
+ * gnutls_x509_crt_get_issuer_dn3:
+ * @cert: should contain a #gnutls_x509_crt_t type
+ * @dn: a pointer to a structure to hold the name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will allocate buffer and copy the name of issuer of the Certificate.
+ * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
+ * described in RFC4514. The output string will be ASCII or UTF-8
+ * encoded, depending on the certificate data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.5.7
+ **/
+int
+gnutls_x509_crt_get_issuer_dn3(gnutls_x509_crt_t cert, gnutls_datum_t *dn, unsigned flags)
+{
+       if (cert == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return _gnutls_x509_get_dn(cert->cert,
+                                  "tbsCertificate.issuer.rdnSequence",
+                                  dn, flags);
 }
 
 /**
@@ -627,6 +666,9 @@ gnutls_x509_crt_get_issuer_dn_oid(gnutls_x509_crt_t cert,
  *
  * If @buf is null then only the size will be filled. 
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crt_get_dn3().
+ *
  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not
  *   long enough, and in that case the @buf_size will be updated
  *   with the required size. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if
@@ -643,7 +685,7 @@ gnutls_x509_crt_get_dn(gnutls_x509_crt_t cert, char *buf,
 
        return _gnutls_x509_parse_dn(cert->cert,
                                     "tbsCertificate.subject.rdnSequence",
-                                    buf, buf_size);
+                                    buf, buf_size, GNUTLS_X509_DN_FLAG_COMPAT);
 }
 
 /**
@@ -656,6 +698,9 @@ gnutls_x509_crt_get_dn(gnutls_x509_crt_t cert, char *buf,
  * described in RFC4514. The output string will be ASCII or UTF-8
  * encoded, depending on the certificate data.
  *
+ * This function does not output a fully RFC4514 compliant string, if
+ * that is required see gnutls_x509_crt_get_dn3().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
  *
@@ -670,7 +715,39 @@ int gnutls_x509_crt_get_dn2(gnutls_x509_crt_t cert, gnutls_datum_t * dn)
 
        return _gnutls_x509_get_dn(cert->cert,
                                   "tbsCertificate.subject.rdnSequence",
-                                  dn);
+                                  dn, GNUTLS_X509_DN_FLAG_COMPAT);
+}
+
+/**
+ * gnutls_x509_crt_get_dn3:
+ * @cert: should contain a #gnutls_x509_crt_t type
+ * @dn: a pointer to a structure to hold the name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will allocate buffer and copy the name of the Certificate.
+ * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
+ * described in RFC4514. The output string will be ASCII or UTF-8
+ * encoded, depending on the certificate data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.5.7
+ **/
+int gnutls_x509_crt_get_dn3(gnutls_x509_crt_t cert, gnutls_datum_t *dn, unsigned flags)
+{
+       if (cert == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return _gnutls_x509_get_dn(cert->cert,
+                                  "tbsCertificate.subject.rdnSequence",
+                                  dn, flags);
 }
 
 /**
@@ -1461,7 +1538,7 @@ _gnutls_parse_general_name2(ASN1_TYPE src, const char *src_name,
                }
        } else if (type == GNUTLS_SAN_DN) {
                _gnutls_str_cat(nptr, sizeof(nptr), ".directoryName");
-               ret = _gnutls_x509_get_dn(src, nptr, dname);
+               ret = _gnutls_x509_get_dn(src, nptr, dname, 0);
                if (ret < 0) {
                        gnutls_assert();
                        goto cleanup;
index a64ca3ed7f5903ca77f110cdcb4ae7c2c5db5a8b..8936a23d0836dcd2708bf48b964d380f3a254b28 100644 (file)
@@ -662,5 +662,36 @@ gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str)
                return GNUTLS_E_INVALID_REQUEST;
        }
 
-       return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str);
+       return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, GNUTLS_X509_DN_FLAG_COMPAT);
+}
+
+/**
+ * gnutls_x509_dn_get_str:
+ * @dn: a pointer to DN
+ * @str: a datum that will hold the name
+ * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
+ *
+ * This function will allocate buffer and copy the name in the provided DN.
+ * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
+ * described in RFC4514. The output string will be ASCII or UTF-8
+ * encoded, depending on the certificate data.
+ *
+ * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
+ * format will match the format output by previous to 3.5.6 versions of GnuTLS
+ * which was not not fully RFC4514-compliant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.5.7
+ **/
+int
+gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str, unsigned flags)
+{
+       if (dn == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, flags);
 }
index 25e013f2fbf582b3d3174cbd824f2e7f5f5db960..4fe0e3dc2a69ca0df87424408376dfc21ea1ca46 100644 (file)
@@ -165,11 +165,13 @@ int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name,
 
 int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
                          const char *asn1_rdn_name, char *buf,
-                         size_t * sizeof_buf);
+                         size_t * sizeof_buf,
+                         unsigned flags);
 
 int
 _gnutls_x509_get_dn(ASN1_TYPE asn1_struct,
-                   const char *asn1_rdn_name, gnutls_datum_t * dn);
+                   const char *asn1_rdn_name, gnutls_datum_t * dn,
+                   unsigned flags);
 
 int
 _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct,