diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-03-05 21:46:26 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-03-05 21:46:26 +0100 |
commit | 92c2dcd836c0c1d32016243d1dd6d1a0df547094 (patch) | |
tree | cd8ec53fdfed16aa792fd270c66eee13795b73a4 | |
parent | ecb901e2b8caea49ca6e835e23ea67a6b9f888b4 (diff) | |
download | gnutls-92c2dcd836c0c1d32016243d1dd6d1a0df547094.tar.gz |
correctly remove revoked certificates. That required quite some backports from the 3.1 branch.
-rw-r--r-- | lib/gnutls_x509.c | 109 | ||||
-rw-r--r-- | lib/x509/verify-high.c | 38 | ||||
-rw-r--r-- | lib/x509/verify-high.h | 4 |
3 files changed, 138 insertions, 13 deletions
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 5bc343ffd6..b81486e424 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -39,6 +39,7 @@ #include <x509_b64.h> #include <gnutls_x509.h> #include "x509/common.h" +#include "x509/verify-high.h" #include "x509/x509_int.h" #include <gnutls_str_array.h> #include "read-file.h" @@ -1643,8 +1644,10 @@ unsigned int i; #elif defined(ANDROID) || defined(__ANDROID__) # include <dirent.h> # include <unistd.h> +# include "read-file.h" + static int load_dir_certs(const char* dirname, gnutls_certificate_credentials_t cred, - unsigned type, unsigned check_revoked) + unsigned type) { DIR * dirp; struct dirent *d; @@ -1659,16 +1662,6 @@ char path[512]; { 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_certificate_set_x509_trust_file (cred, path, type); if (ret >= 0) @@ -1682,6 +1675,92 @@ char path[512]; return r; } +static 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; +} + +static 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; + + { + 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; +} + +static int load_revoked_certs(gnutls_x509_trust_list_t list, unsigned type) +{ +DIR * dirp; +struct dirent *d; +int ret; +int r = 0; +char path[512]; + + 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 int @@ -1689,13 +1768,17 @@ set_x509_system_trust_file (gnutls_certificate_credentials_t cred) { int r = 0, ret; - ret = load_dir_certs("/system/etc/security/cacerts/", cred, GNUTLS_X509_FMT_PEM, 1); + ret = load_dir_certs("/system/etc/security/cacerts/", cred, GNUTLS_X509_FMT_PEM); if (ret >= 0) r += ret; - ret = load_dir_certs("/data/misc/keychain/cacerts-added/", cred, GNUTLS_X509_FMT_DER, 0); + ret = load_dir_certs("/data/misc/keychain/cacerts-added/", cred, GNUTLS_X509_FMT_DER); if (ret >= 0) r += ret; + + ret = load_revoked_certs(cred->tlist, GNUTLS_X509_FMT_DER); + if (ret >= 0) + r -= ret; return r; } diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c index 88407b9ad5..6523f4c19c 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -188,6 +188,44 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list, return i; } +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, ret; + unsigned j; + uint32_t hash; + gnutls_datum_t dn; + + for (i = 0; i < clist_size; i++) + { + ret = gnutls_x509_crt_get_raw_dn(clist[i], &dn); + if (ret < 0) { + gnutls_assert(); + return i; + } + + hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH); + hash %= list->size; + + _gnutls_free_datum(&dn); + + for (j=0;j<list->node[hash].trusted_ca_size;j++) + { + if (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 diff --git a/lib/x509/verify-high.h b/lib/x509/verify-high.h index 67d96c5113..2e9027c594 100644 --- a/lib/x509/verify-high.h +++ b/lib/x509/verify-high.h @@ -22,3 +22,7 @@ int _gnutls_trustlist_inlist (gnutls_x509_trust_list_t list, gnutls_x509_crt_t cert); +int +gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list, + const gnutls_x509_crt_t * clist, + int clist_size); |