]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added functions that remove certificates from a trust list.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 5 Mar 2013 20:28:56 +0000 (21:28 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Tue, 5 Mar 2013 20:28:56 +0000 (21:28 +0100)
NEWS
lib/includes/gnutls/x509.h
lib/libgnutls.map
lib/system.c
lib/x509/verify-high.c
lib/x509/verify-high2.c
tests/x509cert-tl.c

diff --git a/NEWS b/NEWS
index fe8fe673d7f95c421667ad4d7d3738b1600f681a..10b3b44b4a093075c712b2098f4d001d49624728 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,9 @@ gnutls_x509_crt_get_issuer_dn2: Added
 gnutls_x509_crt_get_dn2: Added
 gnutls_x509_crl_get_issuer_dn2: Added
 gnutls_x509_crq_get_dn2: Added
+gnutls_x509_trust_list_remove_trust_mem: Added
+gnutls_x509_trust_list_remove_trust_file: Added
+gnutls_x509_trust_list_remove_cas: Added
 
 
 * Version 3.1.9 (released 2013-02-27)
index 46bd2247b706207f23de61e5e4627a7c675258e8..f460cd293a81ddc706205cc74eb3c4b04c58c235 100644 (file)
@@ -1040,6 +1040,9 @@ extern "C"
   int
   gnutls_x509_trust_list_add_cas (gnutls_x509_trust_list_t list, 
     const gnutls_x509_crt_t * clist, int clist_size, unsigned int flags);
+  int gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
+                               const gnutls_x509_crt_t * clist,
+                               int clist_size);
 
   int gnutls_x509_trust_list_add_named_crt (gnutls_x509_trust_list_t list, 
       gnutls_x509_crt_t cert, const void* name, size_t name_size, unsigned int flags);
@@ -1094,6 +1097,16 @@ gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list,
                                       unsigned int tl_flags,
                                       unsigned int tl_vflags);
 
+int
+gnutls_x509_trust_list_remove_trust_file(gnutls_x509_trust_list_t list,
+                                      const char* ca_file, 
+                                      gnutls_x509_crt_fmt_t type);
+
+int
+gnutls_x509_trust_list_remove_trust_mem(gnutls_x509_trust_list_t list,
+                                     const gnutls_datum_t * cas, 
+                                     gnutls_x509_crt_fmt_t type);
+
 int
 gnutls_x509_trust_list_add_system_trust(gnutls_x509_trust_list_t list,
                                         unsigned int tl_flags, unsigned int tl_vflags);
index 2fd42760f2a79a89aea929a0ff67eefd571be49d..3a793a1521bf2748f0d591c3e8b1a29bd87ee1a5 100644 (file)
@@ -897,6 +897,9 @@ GNUTLS_3_1_0 {
        gnutls_x509_crt_get_dn2;
        gnutls_x509_crl_get_issuer_dn2;
        gnutls_x509_crq_get_dn2;
+       gnutls_x509_trust_list_remove_trust_mem;
+       gnutls_x509_trust_list_remove_trust_file;
+       gnutls_x509_trust_list_remove_cas;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
index c0400d81131b02f2528e1c1f32a5c0df02ba6f60..855b6295345a95355e17a74cb648d44361ddfa45 100644 (file)
@@ -469,8 +469,7 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags, unsig
 # include <dirent.h>
 # include <unistd.h>
 static int load_dir_certs(const char* dirname, gnutls_x509_trust_list_t list, 
-       unsigned int tl_flags, unsigned int tl_vflags, unsigned type,
-       unsigned check_revoked)
+       unsigned int tl_flags, unsigned int tl_vflags, unsigned type)
 {
 DIR * dirp;
 struct dirent *d;
@@ -486,16 +485,6 @@ char path[GNUTLS_PATH_MAX];
          d = readdir(dirp);
          if (d != NULL && d->d_type == DT_REG) 
            {
-               
-               if (check_revoked) 
-                 {
-                   snprintf(path, sizeof(path), 
-                                "/data/misc/keychain/cacerts-removed/%s", d->d_name);
-                   if (access(path, R_OK) == 0)
-                     /* revoked -> do not add */
-                     continue;
-                 }
-
                snprintf(path, sizeof(path), "%s/%s", dirname, d->d_name);
 
                 ret = gnutls_x509_trust_list_add_trust_file(list, path, NULL, type, tl_flags, tl_vflags);
@@ -510,6 +499,37 @@ char path[GNUTLS_PATH_MAX];
   return r;
 }
 
+static int load_revoked_certs(gnutls_x509_trust_list_t list, 
+       unsigned int tl_flags, unsigned int tl_vflags, unsigned type)
+{
+DIR * dirp;
+struct dirent *d;
+int ret;
+int r = 0;
+char path[GNUTLS_PATH_MAX];
+
+  dirp = opendir("/data/misc/keychain/cacerts-removed/");
+  if (dirp != NULL) 
+    {
+      do
+        {
+         d = readdir(dirp);
+         if (d != NULL && d->d_type == DT_REG) 
+           {
+               snprintf(path, sizeof(path), "/data/misc/keychain/cacerts-removed/%s", d->d_name);
+
+                ret = gnutls_x509_trust_list_remove_trust_file(list, path, type);
+                if (ret >= 0)
+                  r += ret;
+           }
+       }
+      while(d != NULL);
+      closedir(dirp);
+    }
+    
+  return r;
+}
+
 /* This works on android 4.x 
  */
 static
@@ -517,14 +537,18 @@ int add_system_trust(gnutls_x509_trust_list_t list, unsigned int tl_flags, unsig
 {
   int r = 0, ret;
 
-  ret = load_dir_certs("/system/etc/security/cacerts/", list, tl_flags, tl_vflags, GNUTLS_X509_FMT_PEM, 1);
+  ret = load_dir_certs("/system/etc/security/cacerts/", list, tl_flags, tl_vflags, GNUTLS_X509_FMT_PEM);
   if (ret >= 0)
     r += ret;
 
-  ret = load_dir_certs("/data/misc/keychain/cacerts-added/", list, tl_flags, tl_vflags, GNUTLS_X509_FMT_DER, 0);
+  ret = load_dir_certs("/data/misc/keychain/cacerts-added/", list, tl_flags, tl_vflags, GNUTLS_X509_FMT_DER);
   if (ret >= 0)
     r += ret;
-  
+    
+  ret = load_revoked_certs(list, tl_flags, tl_vflags);
+  if (ret >= 0)
+    r -= ret;
+
   return r;
 }
 #else
@@ -699,3 +723,4 @@ const char *src = data;
   return 0;
 }
 #endif
+
index ace0bf2672c2110573cd6eae111a3e83e7d3b1d4..d5069a45eec0b39ce710adfa0515ea4cdbdaf8e6 100644 (file)
@@ -184,6 +184,48 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
     return i;
 }
 
+/**
+ * gnutls_x509_trust_list_remove_cas:
+ * @list: The structure of the list
+ * @clist: A list of CAs
+ * @clist_size: The length of the CA list
+ *
+ * This function will remove the given certificate authorities
+ * from the trusted list. 
+ *
+ * Returns: The number of removed elements is returned.
+ *
+ * Since: 3.1.10
+ **/
+int
+gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
+                               const gnutls_x509_crt_t * clist,
+                               int clist_size)
+{
+    int i, r = 0;
+    unsigned j;
+    uint32_t hash;
+
+    for (i = 0; i < clist_size; i++) 
+      {
+        hash = hash_pjw_bare(clist[i]->raw_dn.data, clist[i]->raw_dn.size);
+        hash %= list->size;
+        
+        for (j=0;j<list->node[hash].trusted_ca_size;j++) 
+          {
+           if (_gnutls_check_if_same_cert(clist[i], list->node[hash].trusted_cas[j]) != 0)
+             {
+                list->node[hash].trusted_cas[j] = 
+                       list->node[hash].trusted_cas[list->node[hash].trusted_ca_size-1];
+               list->node[hash].trusted_ca_size--;
+               r++;
+              }
+          }
+      }
+
+    return r;
+}
+
 /**
  * gnutls_x509_trust_list_add_named_crt:
  * @list: The structure of the list
index 039d312e40230c60022fad32bda1a3dbf1c602af..623a4028553e06d3b06e90ba0611b77f22c83d34 100644 (file)
@@ -99,6 +99,50 @@ gnutls_x509_trust_list_add_trust_mem(gnutls_x509_trust_list_t list,
   return r;
 }
 
+/**
+ * gnutls_x509_trust_list_remove_trust_mem:
+ * @list: The structure of the list
+ * @cas: A buffer containing a list of CAs (optional)
+ * @type: The format of the certificates
+ *
+ * This function will add the given certificate authorities
+ * to the trusted list. 
+ *
+ * Returns: The number of added elements is returned.
+ *
+ * Since: 3.1.10
+ **/
+int
+gnutls_x509_trust_list_remove_trust_mem(gnutls_x509_trust_list_t list,
+                                     const gnutls_datum_t * cas, 
+                                     gnutls_x509_crt_fmt_t type)
+{
+  int ret;
+  gnutls_x509_crt_t *x509_ca_list = NULL;
+  unsigned int x509_ncas;
+  unsigned int r = 0, i;
+  
+  if (cas != NULL && cas->data != NULL)
+    {
+      ret = gnutls_x509_crt_list_import2( &x509_ca_list, &x509_ncas, cas, type, 0);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+
+      ret = gnutls_x509_trust_list_remove_cas(list, x509_ca_list, x509_ncas);
+      
+      for (i=0;i<x509_ncas;i++)
+        gnutls_x509_crt_deinit(x509_ca_list[i]);
+      gnutls_free(x509_ca_list);
+
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+      else
+        r += ret;
+    }
+
+  return r;
+}
+
 #ifdef ENABLE_PKCS11
 static 
 int import_pkcs11_url(gnutls_x509_trust_list_t list, const char* ca_file, unsigned int flags)
@@ -144,6 +188,52 @@ cleanup:
   return ret;
 }
 
+static 
+int remove_pkcs11_url(gnutls_x509_trust_list_t list, const char* ca_file)
+{
+gnutls_x509_crt_t *xcrt_list = NULL;
+gnutls_pkcs11_obj_t *pcrt_list = NULL;
+unsigned int pcrt_list_size = 0, i;
+int ret;
+      
+  ret = gnutls_pkcs11_obj_list_import_url2(&pcrt_list, &pcrt_list_size, ca_file, 
+                                           GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED_CA, 0);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+     
+  if (pcrt_list_size == 0)
+    {
+      ret = 0;
+      goto cleanup;
+    }
+      
+  xcrt_list = gnutls_malloc(sizeof(gnutls_x509_crt_t)*pcrt_list_size);
+  if (xcrt_list == NULL)
+    {
+      ret = GNUTLS_E_MEMORY_ERROR;
+      goto cleanup;
+    }
+      
+  ret = gnutls_x509_crt_list_import_pkcs11( xcrt_list, pcrt_list_size, pcrt_list, 0);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto cleanup;
+    }
+  
+  ret = gnutls_x509_trust_list_remove_cas(list, xcrt_list, pcrt_list_size);
+  
+cleanup:
+  for (i=0;i<pcrt_list_size;i++)
+    {
+      gnutls_pkcs11_obj_deinit(pcrt_list[i]);
+      gnutls_x509_crt_deinit(xcrt_list[i]);
+    }
+  gnutls_free(pcrt_list);
+  gnutls_free(xcrt_list);
+
+  return ret;
+}
 #endif
 
 
@@ -214,3 +304,51 @@ gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list,
   return ret;
 }
 
+/**
+ * gnutls_x509_trust_list_remove_trust_file:
+ * @list: The structure of the list
+ * @ca_file: A file containing a list of CAs
+ * @type: The format of the certificates
+ *
+ * This function will add the given certificate authorities
+ * to the trusted list. pkcs11 URLs are also accepted, instead
+ * of files, by this function.
+ *
+ * Returns: The number of added elements is returned.
+ *
+ * Since: 3.1.10
+ **/
+int
+gnutls_x509_trust_list_remove_trust_file(gnutls_x509_trust_list_t list,
+                                      const char* ca_file, 
+                                      gnutls_x509_crt_fmt_t type)
+{
+  gnutls_datum_t cas = { NULL, 0 };
+  size_t size;
+  int ret;
+
+#ifdef ENABLE_PKCS11
+  if (strncmp (ca_file, "pkcs11:", 7) == 0)
+    {
+      ret = remove_pkcs11_url(list, ca_file);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+    }
+  else
+#endif
+    {
+      cas.data = (void*)read_binary_file (ca_file, &size);
+      if (cas.data == NULL)
+        {
+          gnutls_assert ();
+          return GNUTLS_E_FILE_ERROR;
+        }
+      cas.size = size;
+    }
+
+  ret = gnutls_x509_trust_list_remove_trust_mem(list, &cas, type);
+  free(cas.data);
+
+  return ret;
+}
+
index 2753daa185156a8b6a72c4b233a2ab81a97ed8f9..08f25b36ea2ad8b643c32e20b320656a1047efce 100644 (file)
@@ -249,12 +249,28 @@ doit (void)
   if (ret < 1)
     fail("gnutls_x509_trust_list_add_trust_mem: %d (%s)\n", __LINE__, gnutls_strerror(ret));
 
+  ret = gnutls_x509_trust_list_remove_trust_mem(tl, &data, GNUTLS_X509_FMT_PEM);
+  if (ret < 1)
+    fail("gnutls_x509_trust_list_add_trust_mem: %d (%s)\n", __LINE__, gnutls_strerror(ret));
+
   data.data = cert_der;
   data.size = sizeof(cert_der);
   ret = gnutls_x509_trust_list_add_trust_mem(tl, &data, NULL, GNUTLS_X509_FMT_DER, 0, 0);
   if (ret < 1)
     fail("gnutls_x509_trust_list_add_trust_mem: %d (%s)\n", __LINE__, gnutls_strerror(ret));
 
+  ret = gnutls_x509_trust_list_remove_trust_mem(tl, &data, GNUTLS_X509_FMT_DER);
+  if (ret < 1)
+    fail("gnutls_x509_trust_list_add_trust_mem: %d (%s)\n", __LINE__, gnutls_strerror(ret));
+
+  ret = gnutls_x509_trust_list_remove_cas(tl, &ca_crt, 1);
+  if (ret < 1)
+    fail("gnutls_x509_trust_list_add_cas");
+
+  ret = gnutls_x509_trust_list_verify_crt(tl, &server_crt, 1, 0, &status, NULL);
+  if (ret == 0 && status == 0)
+    fail("gnutls_x509_trust_list_verify_crt\n");
+
   gnutls_x509_trust_list_deinit(tl, 1);
   
   gnutls_global_deinit();