]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED flag for gnutls_x509_crt_list_import.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 31 Jul 2011 19:11:49 +0000 (21:11 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 31 Jul 2011 19:16:46 +0000 (21:16 +0200)
It checks whether the list to be imported is properly sorted.

NEWS
lib/gnutls_str.h
lib/gnutls_x509.c
lib/includes/gnutls/x509.h
lib/x509/x509.c
tests/x509cert.c

diff --git a/NEWS b/NEWS
index 6c694bbf589f066d2a72070e690cdc6c70681ff3..eddafc46700cb8c64feb059085d5a69efe44a197 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,12 @@ See the end for copying conditions.
 using gnutls_certificate_set_x509_key*(), is sorted
 according to TLS specification (from subject to issuer).
 
+** libgnutls: Added GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED flag for
+gnutls_x509_crt_list_import. It checks whether the list to be 
+imported is properly sorted.
+
 ** API and ABI modifications:
-No changes since last version.
+GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED: New element in gnutls_certificate_import_flags
 
 
 * Version 3.0.0 (released 2011-07-29)
index 3fb230598aa1df2aa17a74d47b434562560eda73..41f6425f9eee210c996bf059e4e04c3863ed1de2 100644 (file)
@@ -97,6 +97,7 @@ int _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
 int _gnutls_hostname_compare (const char *certname, size_t certnamesize,
                               const char *hostname, int level);
 #define MAX_CN 256
+#define MAX_DN 1024
 
 #define BUFFER_APPEND(b, x, s) { \
         ret = _gnutls_buffer_append_data(b, x, s); \
index fd3537bc39c61d4a78d722d54adadfa5a5288192..1ec822cab55a972d668ff84e62b69dff0b6febe9 100644 (file)
@@ -795,8 +795,8 @@ gnutls_certificate_set_x509_key_mem (gnutls_certificate_credentials_t res,
 static int check_if_sorted(gnutls_pcert_st * crt, int nr)
 {
 gnutls_x509_crt_t x509;
-char prev_dn[MAX_CN];
-char dn[MAX_CN];
+char prev_dn[MAX_DN];
+char dn[MAX_DN];
 size_t prev_dn_size, dn_size;
 int i, ret;
 
index f6bfdd8e78ab3977fdff6337e0b07b078a84f261..09d26090f9fb2b407b66c2ed31294352b803e17b 100644 (file)
@@ -92,12 +92,16 @@ extern "C"
  * @GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED: Fail if the
  *   certificates in the buffer are more than the space allocated for
  *   certificates. The error code will be %GNUTLS_E_SHORT_MEMORY_BUFFER.
+ * @GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED: Fail if the certificates
+ *   in the buffer are not ordered starting from subject to issuer.
+ *   The error code will be %GNUTLS_E_CERTIFICATE_LIST_UNSORTED.
  *
  * Enumeration of different certificate import flags.
  */
   typedef enum gnutls_certificate_import_flags
   {
-    GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1
+    GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1,
+    GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED = 2
   } gnutls_certificate_import_flags;
 
   int gnutls_x509_crt_init (gnutls_x509_crt_t * cert);
index 2adb899914374d0b6635e013455f5191f7b303a0..758490100b43c0586c0dfdceb9119816e4248172 100644 (file)
@@ -3073,6 +3073,52 @@ int ret;
   return 0;
 }
 
+static int check_if_sorted(gnutls_x509_crt_t * crt, int nr)
+{
+char prev_dn[MAX_DN];
+char dn[MAX_DN];
+size_t prev_dn_size, dn_size;
+int i, ret;
+
+  /* check if the X.509 list is ordered */
+  if (nr > 1)
+    {
+
+      for (i=0;i<nr;i++)
+        {
+          if (i>0)
+            {
+              dn_size = sizeof(dn);
+              ret = gnutls_x509_crt_get_dn(crt[i], dn, &dn_size);
+              if (ret < 0)
+                {
+                  ret = gnutls_assert_val(ret);
+                  goto cleanup;
+                }
+              
+              if (dn_size != prev_dn_size || memcmp(dn, prev_dn, dn_size) != 0)
+                {
+                  ret = gnutls_assert_val(GNUTLS_E_CERTIFICATE_LIST_UNSORTED);
+                  goto cleanup;
+                }
+            }
+
+          prev_dn_size = sizeof(prev_dn);
+          ret = gnutls_x509_crt_get_issuer_dn(crt[i], prev_dn, &prev_dn_size);
+          if (ret < 0)
+            {
+              ret = gnutls_assert_val(ret);
+              goto cleanup;
+            }
+        }
+    }
+
+  ret = 0;
+
+cleanup:
+  return ret;
+}
+
 
 /**
  * gnutls_x509_crt_list_import:
@@ -3086,6 +3132,12 @@ int ret;
  * to the native gnutls_x509_crt_t format. The output will be stored
  * in @certs.  They will be automatically initialized.
  *
+ * The flag %GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED will cause
+ * import to fail if the certificates in the provided buffer are more
+ * than the available structures. The %GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED
+ * flag will cause the function to fail if the provided list is not
+ * sorted from subject to issuer.
+ *
  * If the Certificate is PEM encoded it should have a header of "X509
  * CERTIFICATE", or "CERTIFICATE".
  *
@@ -3205,6 +3257,16 @@ gnutls_x509_crt_list_import (gnutls_x509_crt_t * certs,
 
   *cert_max = count;
 
+  if (flags & GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED)
+    {
+      ret = check_if_sorted(certs, *cert_max);
+      if (ret < 0)
+        {
+          gnutls_assert();
+          goto error;
+        }
+    }
+
   if (nocopy == 0)
     return count;
   else
index 6007b95d8fe57bce311d6b8040f347e5d7a0f6db..2b7c8e8598a60664097cdda1f11da9a1d88e8000 100644 (file)
@@ -80,7 +80,19 @@ static unsigned char cert_pem[] =
   "+62SbuYGpFYsouHAUyfI8pUwCwYJKoZIhvcNAQEFA4GBALujmBJVZnvaTXr9cFRJ\n"
   "jpfc/3X7sLUsMvumcDE01ls/cG5mIatmiyEU9qI3jbgUf82z23ON/acwJf875D3/\n"
   "U7jyOsBJ44SEQITbin2yUeJMIm1tievvdNXBDfW95AM507ShzP12sfiJkJfjjdhy\n"
-  "dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n";
+  "dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n"
+  "-----BEGIN CERTIFICATE-----\n"
+  "MIIB5zCCAVKgAwIBAgIERiYdJzALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n"
+  "VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTExWhcNMDgwNDE3MTMyOTExWjAZMRcw\n"
+  "FQYDVQQDEw5HbnVUTFMgdGVzdCBDQTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA\n"
+  "vuyYeh1vfmslnuggeEKgZAVmQ5ltSdUY7H25WGSygKMUYZ0KT74v8C780qtcNt9T\n"
+  "7EPH/N6RvB4BprdssgcQLsthR3XKA84jbjjxNCcaGs33lvOz8A1nf8p3hD+cKfRi\n"
+  "kfYSW2JazLrtCC4yRCas/SPOUxu78of+3HiTfFm/oXUCAwEAAaNDMEEwDwYDVR0T\n"
+  "AQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBTpPBz7rZJu5gak\n"
+  "Viyi4cBTJ8jylTALBgkqhkiG9w0BAQUDgYEAiaIRqGfp1jPpNeVhABK60SU0KIAy\n"
+  "njuu7kHq5peUgYn8Jd9zNzExBOEp1VOipGsf6G66oQAhDFp2o8zkz7ZH71zR4HEW\n"
+  "KoX6n5Emn6DvcEH/9pAhnGxNHJAoS7czTKv/JDZJhkqHxyrE1fuLsg5Qv25DTw7+\n"
+  "PfqUpIhz5Bbm7J4=\n" "-----END CERTIFICATE-----\n";
 const gnutls_datum_t cert = { cert_pem, sizeof (cert_pem) };
 
 static unsigned char key_pem[] =
@@ -142,15 +154,17 @@ const gnutls_datum_t server_key = { server_key_pem,
   sizeof (server_key_pem)
 };
 
-
+#define LIST_SIZE 3
 void
 doit (void)
 {
   gnutls_certificate_credentials_t x509_cred;
-  int ret;
-  gnutls_x509_crt_t crt, issuer;
+  int ret, i;
+  gnutls_x509_crt_t issuer;
+  gnutls_x509_crt_t list[LIST_SIZE];
   char dn[128];
   size_t dn_size;
+  unsigned int list_size;
 
   /* this must be called once in the program
    */
@@ -167,12 +181,13 @@ doit (void)
                                        GNUTLS_X509_FMT_PEM);
 
   /* test for gnutls_certificate_get_issuer() */
-  gnutls_x509_crt_init(&crt);
-  ret = gnutls_x509_crt_import(crt, &cert, GNUTLS_X509_FMT_PEM);
-  if (ret < 0)
-    fail("gnutls_x509_crt_import");
   
-  ret = gnutls_certificate_get_issuer(x509_cred, crt, &issuer, 0);
+  list_size = LIST_SIZE;
+  ret = gnutls_x509_crt_list_import(list, &list_size, &cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
+  if (ret < 0)
+    fail("gnutls_x509_crt_list_import");
+
+  ret = gnutls_certificate_get_issuer(x509_cred, list[0], &issuer, 0);
   if (ret < 0)
     fail("gnutls_certificate_get_isser");
 
@@ -182,7 +197,8 @@ doit (void)
     fail("gnutls_certificate_get_isser");
   
   fprintf(stderr, "Issuer's DN: %s\n", dn);
-  gnutls_x509_crt_deinit(crt);
+  for (i=0;i<list_size;i++)
+    gnutls_x509_crt_deinit(list[i]);
   gnutls_certificate_free_credentials(x509_cred);
   
   success("success");