diff options
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 31 | ||||
-rw-r--r-- | lib/pkcs11_privkey.c | 5 | ||||
-rw-r--r-- | lib/urls.c | 92 | ||||
-rw-r--r-- | lib/urls.h | 21 | ||||
-rw-r--r-- | lib/x509/x509.c | 20 |
6 files changed, 158 insertions, 13 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index b1b680068c..ce82c92f78 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -83,7 +83,7 @@ COBJECTS = gnutls_range.c gnutls_record.c \ gnutls_pubkey.c locks.c gnutls_dtls.c system_override.c \ crypto-backend.c verify-tofu.c pin.c tpm.c fips.c \ safe-memfuncs.c inet_pton.c atfork.c atfork.h system-keys.c \ - system-keys.h + system-keys.h urls.c urls.h if ENABLE_SELF_CHECKS COBJECTS += crypto-selftests.c crypto-selftests-pk.c diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 3a82cb834b..b582d61f0a 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -45,6 +45,7 @@ #include <gnutls/x509.h> #include "read-file.h" #include "system-keys.h" +#include "urls.h" #ifdef _WIN32 #include <wincrypt.h> #endif @@ -656,17 +657,22 @@ read_key_mem(gnutls_certificate_credentials_t res, /* Reads a private key from a token. */ static int -read_key_url(gnutls_certificate_credentials_t res, const char *url) +read_key_url(gnutls_certificate_credentials_t res, const char *_url) { int ret; gnutls_privkey_t pkey = NULL; + char *url; + + url = _gnutls_sanitize_url(_url, 1); + if (url == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); /* allocate space for the pkey list */ ret = gnutls_privkey_init(&pkey); if (ret < 0) { gnutls_assert(); - return ret; + goto cleanup; } if (res->pin.cb) @@ -685,9 +691,11 @@ read_key_url(gnutls_certificate_credentials_t res, const char *url) goto cleanup; } + gnutls_free(url); return 0; cleanup: + gnutls_free(url); if (pkey) gnutls_privkey_deinit(pkey); @@ -699,7 +707,7 @@ read_key_url(gnutls_certificate_credentials_t res, const char *url) /* Reads a certificate key from a token. */ static int -read_cert_url(gnutls_certificate_credentials_t res, const char *url) +read_cert_url(gnutls_certificate_credentials_t res, const char *_url) { int ret; gnutls_x509_crt_t crt = NULL; @@ -707,13 +715,24 @@ read_cert_url(gnutls_certificate_credentials_t res, const char *url) gnutls_str_array_t names; gnutls_datum_t t = {NULL, 0}; unsigned i, count = 0; + unsigned is_pkcs11 = 0; + char *url; + + url = _gnutls_sanitize_url(_url, 0); + if (url == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + if (strncmp(url, "pkcs11:", 7) == 0) { + is_pkcs11 = 1; + } _gnutls_str_array_init(&names); ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN); if (ccert == NULL) { gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; } ret = gnutls_x509_crt_init(&crt); @@ -758,7 +777,7 @@ read_cert_url(gnutls_certificate_credentials_t res, const char *url) count++; #ifdef ENABLE_PKCS11 - if (strncmp(certfile, "pkcs11:", 7) == 0) { + if (is_pkcs11 != 0) { ret = gnutls_pkcs11_get_raw_issuer(url, crt, &t, GNUTLS_X509_FMT_DER, 0); if (ret < 0) break; @@ -793,10 +812,12 @@ read_cert_url(gnutls_certificate_credentials_t res, const char *url) if (crt != NULL) gnutls_x509_crt_deinit(crt); + gnutls_free(url); return 0; cleanup: if (crt != NULL) gnutls_x509_crt_deinit(crt); + gnutls_free(url); gnutls_free(t.data); _gnutls_str_array_clear(&names); gnutls_free(ccert); diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index f06121d848..d59b77c9d5 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -28,6 +28,7 @@ #include <gnutls_sig.h> #include <gnutls_pk.h> #include <fips.h> +#include "urls.h" #include <p11-kit/uri.h> /* In case of a fork, it will invalidate the open session @@ -402,11 +403,11 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey, memset(&pkey->sinfo, 0, sizeof(pkey->sinfo)); - pkey->url = gnutls_strdup(url); + pkey->url = _gnutls_sanitize_url(url, 1); if (pkey->url == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - ret = pkcs11_url_to_info(url, &pkey->uinfo); + ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo); if (ret < 0) { gnutls_assert(); return ret; diff --git a/lib/urls.c b/lib/urls.c new file mode 100644 index 0000000000..f68bec71cb --- /dev/null +++ b/lib/urls.c @@ -0,0 +1,92 @@ +/* + * Copyright © 2014 Nikos Mavrogiannopoulos + * + * Author: Nikos Mavrogiannopoulos + * + * GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#include <gnutls_int.h> +#include <gnutls_errors.h> +#include <gnutls_str.h> +#include "urls.h" + +static const char *_types[] = +{ "object-type=cert", "object-type=private", NULL }; + +static char *append_to_str(const char *str1, const char *str2) +{ + char *str = NULL; + gnutls_buffer_st buf; + int ret; + + _gnutls_buffer_init(&buf); + + ret = _gnutls_buffer_append_str(&buf, str1); + if (ret < 0) { + goto cleanup; + } + + ret = _gnutls_buffer_append_data(&buf, ";", 1); + if (ret < 0) { + goto cleanup; + } + + ret = _gnutls_buffer_append_str(&buf, str2); + if (ret < 0) { + goto cleanup; + } + + ret = _gnutls_buffer_append_data(&buf, "\x00", 1); + if (ret < 0) { + goto cleanup; + } + + str = (void*)buf.data; + ret = 0; +fprintf(stderr, "str: %s\n", str); + cleanup: + if (ret < 0) { + _gnutls_buffer_clear(&buf); + } + return str; + +} + +/* + * @type: 0 for cert, 1 for privkey + * + * This function will make sure that the URL is ok (e.g., + * that it contains type=cert, when it is a certificate, + * or type=privkey for PKCS #11 URLs. That allows to use + * the common URL part as input for keys and certificates. + * + * + */ +char *_gnutls_sanitize_url(const char *url, unsigned type) +{ +#ifdef ENABLE_PKCS11 + if (strncmp(url, "pkcs11:", 7) == 0) { + if (strstr(url, _types[type]) != NULL) { + return gnutls_strdup(url); + } else { + return append_to_str(url, _types[type]); + } + } else +#endif + { + return gnutls_strdup(url); + } +} diff --git a/lib/urls.h b/lib/urls.h new file mode 100644 index 0000000000..5473359bac --- /dev/null +++ b/lib/urls.h @@ -0,0 +1,21 @@ +/* + * Copyright © 2014 Nikos Mavrogiannopoulos + * + * Author: Nikos Mavrogiannopoulos + * + * GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +char *_gnutls_sanitize_url(const char *url, unsigned type); diff --git a/lib/x509/x509.c b/lib/x509/x509.c index d8c54356c5..211a4c0634 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -34,6 +34,7 @@ #include <libtasn1.h> #include <gnutls_pk.h> #include <pkcs11_int.h> +#include "urls.h" #include "system-keys.h" static int crt_reinit(gnutls_x509_crt_t crt) @@ -3810,13 +3811,22 @@ int gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt, const char *url, unsigned int flags) { - if (strncmp(url, "system:", 7) == 0) { - return _gnutls_x509_crt_import_system_url(crt, url); + char *xurl; + int ret; + + xurl = _gnutls_sanitize_url(url, 0); + if (xurl == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + if (strncmp(xurl, "system:", 7) == 0) { + ret = _gnutls_x509_crt_import_system_url(crt, xurl); #ifdef ENABLE_PKCS11 - } else if (strncmp(url, "pkcs11:", 7) == 0) { - return _gnutls_x509_crt_import_pkcs11_url(crt, url, flags); + } else if (strncmp(xurl, "pkcs11:", 7) == 0) { + ret = _gnutls_x509_crt_import_pkcs11_url(crt, xurl, flags); #endif } else { - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } + gnutls_free(xurl); + return ret; } |